This forum is in archive mode. You will not be able to post new content.

Author Topic: [C++] IRC Bot Library (unfinished)  (Read 4104 times)

0 Members and 1 Guest are viewing this topic.

Offline dense

  • Serf
  • *
  • Posts: 23
  • Cookies: 4
    • View Profile
[C++] IRC Bot Library (unfinished)
« on: June 17, 2013, 05:30:52 PM »
This is a IRC Bot library I was working on a while ago. It's some basic stuff for bots and a nice little way to add new commands :)

It's unfinished and probably badly done but it works :D

IRCBot.h
Code: [Select]
#ifndef IRCLIB_H_INCLUDED
#define IRCLIB_H_INCLUDED

/* IRC Library for IRC Bots by dense */

#include <windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <map>
#include <vector>

namespace IRC {
    struct Info {
        char *user;   // User
        char *nick;   // Nickname
    };

    struct Connection {
        int iError;
        WORD wsaVersion;
        WSADATA wsaData;
        char *server;
        int port;
        int sock;

        char buffer[512];
    };

    void error(char *message);
    void setInfo(char *cUser, char *cNick);
    void checkCMDs(char *data);

    char* getIP(char *data);

    int Recv(char *data);

    void sendRAW(char *data);
    void connect(char *server, int port);

    void addCommand(std::string s, void (*fp)(char**));

    extern std::map<std::string, void (*)(char**)> cmds;
    extern struct Connection conn;
    extern struct Info info;
};

#endif // IRCLIB_H_INCLUDED

IRCBot.cpp
Code: [Select]
#include "irclib.h"

namespace IRC
{
    struct Info info;
    struct Connection conn;

    std::map<std::string, void (*)(char**)> cmds;

    void connect(char *server, int port){
        conn.wsaVersion = MAKEWORD(2, 0);
        conn.iError = WSAStartup(conn.wsaVersion, &conn.wsaData);

        if(conn.iError != 0) error("[!]Winsock startup failed!");

        conn.sock = socket(AF_INET, SOCK_STREAM, 0);
        if(conn.sock < 0) error("[!]Error in socket!");

        struct sockaddr_in s;

        s.sin_family = AF_INET;
        s.sin_port = htons(port);
        s.sin_addr.s_addr = inet_addr(getIP(server));

        conn.iError = connect(conn.sock, (struct sockaddr *) &s, sizeof s);
        if(conn.iError < 0) error("[!]Error connecting socket!");

        Sleep(2000);

        memset(conn.buffer, 0, sizeof(conn.buffer));
        sprintf(conn.buffer, "USER %s \"\" \"\" :%s\r\n", info.user, "NULL");
        send(conn.sock, conn.buffer, strlen(conn.buffer), 0);
        memset(conn.buffer, 0, sizeof(conn.buffer));
        sprintf(conn.buffer, "NICK %s\r\n", info.nick);
        send(conn.sock, conn.buffer, strlen(conn.buffer), 0);
        memset(conn.buffer, 0, sizeof(conn.buffer));
    }

    void sendRAW(char *data){
        memset(conn.buffer, 0, sizeof(conn.buffer));
        strcpy(conn.buffer, data);
        std::cout << data << std::endl;
        send(conn.sock, conn.buffer, strlen(conn.buffer), 0);
    }

    int Recv(char *data){
        conn.iError = recv(conn.sock, conn.buffer, sizeof(conn.buffer), 0);
        strcpy(data, conn.buffer);
        memset(conn.buffer, 0, sizeof(conn.buffer));

        return conn.iError;
    }

    char** getCmdData(char* data){
        char *tok;
        tok = strtok(data, " ");

        std::vector<char *> sdata;

        while(tok != NULL){
            sdata.push_back(tok);
            tok = strtok(NULL, " ");
        }

        char *result[sdata.size()];
        std::copy(sdata.begin(), sdata.end(), result);

        return result;
    }

    void checkCMDs(char *data){
        std::string sdata = data;

        typedef std::map<std::string, void(*)(char**)>::iterator it_type;
        for(it_type i = cmds.begin(); i != cmds.end(); i++) {
            if(sdata.find(i->first) != std::string::npos){
                i->second(getCmdData(data));
            }
        }

    }

    void addCommand(std::string cmd, void (*fp)(char**)){
        cmds[cmd] = fp;
    }

    void error(char *message){
        std::cout << message << std::endl;
        closesocket(conn.sock);
        WSACleanup();
        exit(1);
    }

    char* getIP(char *data){
        hostent *record = gethostbyname(data);
        in_addr *address = (in_addr * )record->h_addr;
        char* ipaddr = inet_ntoa(* address);

        return ipaddr;
    }

    void setInfo(char *cUser, char *cNick){
        info.user = cUser;
        info.nick = cNick;
    }
}

example.cpp
Code: [Select]
// Example IRC Bot //
// by dense        //

#include <iostream>
#include "irclib.h"

void join(char** data);

int main(){
    IRC::setInfo("JohnSmith", "JSmith");
    IRC::connect("irc.rizon.net", 6667);

    IRC::addCommand(":.join", join);

    char data[512], suffix[512];
    int error = 0;

    while(1){
        memset(data, 0, sizeof(data));
        error = IRC::Recv(data);
        if(error <= 0) break;

        std::cout << data << std::endl;
        IRC::checkCMDs(data);

        if(sscanf(data, "PING :%s", suffix) > 0){
            sprintf(data, "PONG :%s\r\n", suffix);
            IRC::sendRAW(data);
        }
    }

    return 0;
}

void join(char** data){
    std::string str2 = data[4];
    std::string str = "JOIN " + str2 + "\r\n";
    IRC::sendRAW((char*)str.c_str());
}

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
Re: [C++] IRC Bot Library (unfinished)
« Reply #1 on: June 17, 2013, 05:40:08 PM »
It is nice to see you actually posting your projects :D I'm no c++ expert so I can't give any advice :P I think this will come in handy for some of my future projects :)
+1 man!

Offline dense

  • Serf
  • *
  • Posts: 23
  • Cookies: 4
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #2 on: June 17, 2013, 06:02:12 PM »
Thanks, glad it's useful to someone :)

xC

  • Guest
Re: [C++] IRC Bot Library (unfinished)
« Reply #3 on: June 17, 2013, 11:14:45 PM »
Thanks for the share, however IRC bots are somewhat obsolete. All traffic is usually detected by most anti-malware programs nowadays. No getting around that unless you have a custom protocol. +1 for the effort, code is clean none the less.

Offline ande

  • Owner
  • Titan
  • *
  • Posts: 2664
  • Cookies: 256
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #4 on: June 17, 2013, 11:35:36 PM »
Thanks for the share, however IRC bots are somewhat obsolete. All traffic is usually detected by most anti-malware programs nowadays. No getting around that unless you have a custom protocol. +1 for the effort, code is clean none the less.

Not true at all. You have to keep in mind that a bot is not necessarily malicious. There are millions of bots out there that does non-malicious tasks.


As for AV's picking up on the protocol. So what? IRC is not illegal. If your AV tells you you have a virus because of IRC protocol activity, your AV is pure shit. Besides, switch the port number and enable SSL and the AV wont be able to tell the difference between random SSL encrypted traffic and IRC traffic. No need for a custom protocol. Worst-case scenario, just write an encrypted proxy tunnel for it.


I would like to add tho that yes. IRC bots for malicious use is on the way to become something from the past. But I don't think that is because of AV's detecting it.
I believe malware designers are moving away from IRC because:
1. It doesn't scale in a cost-effective way for large networks.
2. its CLI. People want GUI's and nice statistics. And this is much easier achieved with web based interfaces.




@OP:
It would be nice if you wrote this as classes instead of namespaces. So that one could create multiple IRC instances in one program. Something like:
Code: (cpp) [Select]
int main()
{
    IRCc myFirstIRC = new IRCc('irc.evilzone.org', 6667, 'ande', 'ande');
    IRCc mySecondIRC = new IRCc('irc.evilzone.org', 6667, 'ande2', 'ande2');

    if(myFirstIRC.connected) {
        myFirstIRC.join('#evilzone');
        myFirstIRC.privmsg('#evilzone', 'Hello world!');
    }

    if(mySecondIRC.connected) {
        mySecondIRC.join('#evilzone');
        mySecondIRC.privmsg('#evilzone', 'Hello world2!');
    }
}
« Last Edit: June 17, 2013, 11:48:33 PM by ande »
if($statement) { unless(!$statement) { // Very sure } }
https://evilzone.org/?hack=true

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
Re: [C++] IRC Bot Library (unfinished)
« Reply #5 on: June 18, 2013, 06:15:27 AM »
Also I'd like to ask why is this unfinished? what is it missing?

Offline Stackprotector

  • Administrator
  • Titan
  • *
  • Posts: 2515
  • Cookies: 205
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #6 on: June 18, 2013, 09:38:09 AM »
What's up with all the initialize through memset and use of memcpy. Are you programming C++ or what ? :D
~Factionwars

Offline dense

  • Serf
  • *
  • Posts: 23
  • Cookies: 4
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #7 on: June 18, 2013, 12:56:24 PM »
Yep, this wasn't really made for any malicious bots more for general purpose bots.

It's unfinished cause it's mostly bare bones right now and not very library-ish cause not everything is being done behind the scenes. If you look at the example bot, you can see that a lot of stuff is being managed by the user (like the PING PONG stuff) which defeats the purpose of having a library at all.

What's up with all the initialize through memset and use of memcpy. Are you programming C++ or what ? :D

That's WinAPI's fault, mostly. Because a lot of it is written in C, functions don't use std::string but use c strings which force me to use it's annoying functions.





Offline Stackprotector

  • Administrator
  • Titan
  • *
  • Posts: 2515
  • Cookies: 205
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #8 on: June 18, 2013, 01:00:43 PM »
Yep, this wasn't really made for any malicious bots more for general purpose bots.

It's unfinished cause it's mostly bare bones right now and not very library-ish cause not everything is being done behind the scenes. If you look at the example bot, you can see that a lot of stuff is being managed by the user (like the PING PONG stuff) which defeats the purpose of having a library at all.

That's WinAPI's fault, mostly. Because a lot of it is written in C, functions don't use std::string but use c strings which force me to use it's annoying functions.






Ever tried the string::c_str() function?

Code: (c++) [Select]
#include <string.h>
#include <cstring>

int lol(char lol[])

int main()
{
    std::string lol = "yaaay";
    lol(lol.c_str());
    return 1337;
}
~Factionwars

Offline dense

  • Serf
  • *
  • Posts: 23
  • Cookies: 4
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #9 on: June 18, 2013, 01:38:15 PM »
Yes, actually I did think about converting but it would only save me time in certain places where there was string building, it wouldn't really change much.
« Last Edit: June 18, 2013, 01:38:34 PM by dense »

Offline bluechill

  • Cybermancer
  • Royal Highness
  • ****
  • Posts: 682
  • Cookies: 344
  • I am the existence in these walls
    • View Profile
Re: [C++] IRC Bot Library (unfinished)
« Reply #10 on: June 26, 2013, 01:25:27 AM »

Yes, actually I did think about converting but it would only save me time in certain places where there was string building, it wouldn't really change much.


It would be more C++ like.  For instance, if you were using BSD sockets (which is similar to WinSock and what WinSock is based on to a certain extent), it would look more like this:


Code: (c++) [Select]
//Connect to the server
bool IrcBase::connectToHost(std::string &nameOfServer, unsigned short portnum)
{
    //Use the standard namespace
    using namespace std;
   
    //C struct "hints"
    struct addrinfo hints;
    //C struct for the server info
    struct addrinfo *servInfo;
   
    //Zero out hints
    memset(&hints, 0, sizeof(hints));
   
    //Set our family
    hints.ai_family = AF_UNSPEC;
    //Set the socket type
    hints.ai_socktype = SOCK_STREAM;
   
    //String stream for converting our port number to a string
    stringstream convertPort;
    //Do the converting
    convertPort << portnum;
   
    //Get the host's address (IP)
    int status; //Variable for the result of getaddrinfo
    string portstr = convertPort.str(); //Get the conversion
    if ((status = getaddrinfo(nameOfServer.c_str(), portstr.c_str(), &hints, &servInfo)) != 0)
    {
        //We didn't find it :P
        cout << "Couldn't get address for " << nameOfServer << endl;
        return false;
    }
   
    //Loop through the results & connect
    struct addrinfo *pointer;
   
    for (pointer = servInfo; pointer != NULL; pointer = pointer->ai_next)
    {
        //Finally, get the socket & check whether there was an error
        if ( (socketFS = socket(pointer->ai_family, pointer->ai_socktype, pointer->ai_protocol) ) < 0)
        {
            //We got an error :P
            cout << "Could not create socket!" << endl;
            continue;
        }
       
        //Connect! Yay!
        if (connect(socketFS, pointer->ai_addr, pointer->ai_addrlen) < 0 )
        {
            //Got an error :P
            cout << "Could not connect to server" << endl;
            continue;
        }
       
        //Break from the loop because we've got a valid connection
        break;
    }
   
    //Check if we have a valid connection
    if (pointer == NULL)
    {
        //Nope we don't, we failed to connect
        cout << "Failed to connect server" << endl;
        cout << "Error: " << strerror( errno ) << endl;
    }


    freeaddrinfo(servInfo);
   
    return true;
}


Yes it is similar but allows for things like this:


Code: (c++) [Select]
//Check for ping requests and then respond appropriately
void IrcBase::checkAndParsePing(std::string &input)
{
    //Use the standard namespace
    using namespace std;
   
    //Check to see if it's a PING request
    unsigned long positionOfPing = input.find("PING");
    //Make sure we find PING and it's at the first (0) position
    if (positionOfPing != string::npos && positionOfPing == 0)
    {
        //Make sure it's a valid PING request
        unsigned long positionOfColon = input.find(":");
        //Make sure it's valid and we found the colon
        if (positionOfColon != string::npos)
        {
            //We found it
            //Get the ping request
            string pingResponse = input.substr(positionOfColon + 1, input.length() - positionOfColon - 1);
                       
            //Write to the socket the completed PONG response
            writeToSocket("PONG :" + pingResponse + "\r\n", true);
            //Set the input to nothing so the client doesn't do anything
            input = "";
        }
    }
 
}


As I'm sure you can tell, this is from my own IRCBaseBot which is an IRC bot which features modular plugin loading and a few other features.  I do everything in C++ and it allows for very flexible features in the C++ code.  So just because one portion would look more C than C++ doesn't mean your entire bot should be C in C++.
I have dreamed a dream, but now that dream has gone from me.  In its place now exists my own reality, a reality which I have created for myself by myself.

 



Want to be here? Contact Ande, Factionwars or Kulverstukas on the forum or at IRC.