SMTP电子邮电技术揭密

SMTP电子邮电技术揭密 <首发于黑客X档案2003-2004年中期合订本>

                                                                                  作者:LionD8

SMTP又叫简单邮件传输协议,我们平时发的电子邮件就是利用的这个协议进行传输的,同时电子邮件也经常被黑客们利用进行一些攻击,比如伪造,或者攻击邮件服务器的电子邮件炸弹,在大家用这些黑软的同时有没有想过其中的技术内幕啊?现在我就起以一个抛砖引玉的作用简单的介绍一下电子邮件利用的技术和具体的实现方法。

一.首先我们必须简单的介绍一下SMTP邮件协议。SMTP服务默认是打开的25端口,我们下面用163的邮件服务器为例,来进行电子邮件伪造的实现。

  1.首先要发邮件必须连接到邮件服务器上,然后发送HELO命令和服务器打招呼。命令格式 HELO<SP>意思就是,你好,我是某某。比如说HELO root。服务器会返回  250表示我们的请求成功。

    2.然后我们就应该发送是谁发送的电子邮件,比如:MAILFROM:hacker@hacker.com伪造一个发送者。如果成功也会返回250。

3.然后我们要让邮件服务器知道,我们要给谁发送邮件。发送命令:RCPT TO:xiaoji198288@163.com xiaoji198288@163.com为我们收件人的地址。一会我们就会用这个地址来试验。

4.收件人确定后我们就应该发送电子邮件的正文的数据了。发送命令:DATA。然后就是发送我们的邮件的内容。在邮件正文发送完毕后最后发送<CRLF>.<CRLF>告诉服务器邮件正文发送结束。

5.最后我们发送命令:QUIT。断开和邮件服务器的连接。到这里我们的整个邮件发送过程就结束了。也许您还觉得上面的过程比较空洞,没有关系下面我们将用代码来证实上面的每一个过程。

.代码和注释部分。

首先我们定义一个CMAIL类。

class CEmail 

{

public:

        void CBase64Encode(char* pSr,char* pDes,int nSourLen); //BASE64编码用于发送附件。

    void Sender();      //发送电子邮件

    CString m_FileName; //作为附件的文件名

    CString m_MailDes;  //收件人的油箱

    CString m_ServerIP; //MX记录IP,我们试验用的是163的MX记录,一会我们将介绍MX记录IP的查询方法。

    SOCKET  m_sock;     //一个套结字

    CEmail(CString FileName,CString SIP="", CString DES=""); //构造函数

    virtual ~CEmail();

};

下面我们简单的介绍一下MX邮件服务器的查询方法和BASE64编码。

MX记录查询:在CMD下输入 nslookup -qt=MX 163.com 回车。

MX记录的IP就是类似下面的返回结果:

G:/>nslookup -qt=MX 163.com

*** Can't find server name for address 211.158.22.118: No response from server

Server:  dns.cta.net.cn

Address:  61.128.128.68

Non-authoritative answer:

163.com MX preference = 50, mail exchanger = m203.163.com

163.com MX preference = 50, mail exchanger = m209.163.com

163.com MX preference = 50, mail exchanger = m210.163.com

163.com nameserver = ns.nease.net

163.com nameserver = ns2.nease.net

m209.163.com    internet address = 202.108.44.209

m210.163.com    internet address = 202.108.44.210

m203.163.com    internet address = 202.108.44.203

202.108.44.203 202.108.44.209 202.108.44.210 都是MX邮件服务器IP

我们选用的第一个202.108.44.203作为试验对象。

BASE64编码: 由于SMTP仅仅局限7位的ASCII码,由于电子邮件的用途广泛于是出现了MIME。MIME没有改动SMTP,只是在遵循SMTP的规则上对其进行了一些扩充,包括邮件头部,和非ASCII码的编码规则,用得最广泛的就是BASE64编码。由于附件不一定是纯文本格式,大多都是流式文件即2进制文件。所以对2进制文件进行编码。首先将24位(3个字节的)数据分为4个6位组。6位一共有64种值,分别对应A--Za--z0--9+/

==和=分别表示最后一组只有8为或者为16位的数据。例如:01001001 00110001 01111001 对应编码为:010010 010011 000101 111001。BASE64编码:STE5。

    基本的都介绍完了,下面就是发送邮件的主体部分了。

CEmail::CEmail(CString FileName, CString SIP, CString DES)

{

    m_FileName = FileName;

    m_ServerIP = SIP;

    m_MailDes = DES;

        m_sock = NULL;

}  //构造函数进行函数的初始化

//发送的主体函数

void CEmail::Sender()

{

    if ((m_sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)

    {

        AfxMessageBox("m_sock False");

        exit(1);

    }    //TCP套结字

    SOCKADDR_IN addr_in={0};

    char* pbuf=NULL;

    pbuf = m_FileName.GetBuffer(m_FileName.GetLength()); //取得文件名字并转换为char*型。

    char* next = 0;

    while( next=strstr(pbuf,"//") )

    pbuf=next+1;    //获得文件的第一个字母

    addr_in.sin_family=AF_INET;

    addr_in.sin_port=htons(25);

    addr_in.sin_addr.S_un.S_addr=inet_addr(m_ServerIP);   //MX邮件记录IP

    while (1)

    {

        int ret=connect(m_sock,(struct sockaddr* )&addr_in,sizeof(addr_in));

        if ( ret != SOCKET_ERROR)

        break;

        Sleep(1000);

    } //连接远程服务器。如果成功就跳出死循环。

    char* pTString="helo root/r/n";

    char buf[256]={0};

    send (m_sock,pTString,strlen(pTString),0); //发送helo命令

    Sleep(1000);

    recv (m_sock,buf,256,0); //接收返回的信息                 

    memset(buf,0,256);

    CString tmp="";

    tmp="mail from:LionD8@CQSN.com/r/n";

    send (m_sock,tmp,tmp.GetLength(),0);  //发送mail from命令

    recv (m_sock,buf,256,0);

    memset(buf,0,256);

    tmp="rcpt to:"+m_MailDes+"/r/n";

    send (m_sock,tmp,tmp.GetLength(),0);  //发送rcpt to命令

    recv (m_sock,buf,256,0);

    memset(buf,0,256);

    tmp = "data/r/n";

    send (m_sock,tmp,tmp.GetLength(),0);  //发送data命令

    recv (m_sock,buf,256,0);

    memset(buf,0,256);

    //MIME头部

    tmp = "Subject:";

    tmp += m_Title;

    tmp+="/n";   //邮件的主题

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "From:"+m_SenderName+"/n";  //我们伪造的发件人

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "To:"+m_MailDes+"/r/n";    //收件人

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "Content-Type:multipart/mix;boundary=qwertyuiop/r/n";

    //定义分段的标示为qwertyuiop.

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "/n--qwertyuiop/n/n";

    send (m_sock,tmp,tmp.GetLength(),0);

    m_StringText+="/n";

    send (m_sock,m_StringText,m_StringText.GetLength(),0); //发送正文内容

    void *basepointer;

    tmp = "--qwertyuiop/n";

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "Content-Type: application/octet-stream; name=";

    tmp+=pbuf;

    tmp+="/n";

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "Content-Transfer-Encoding: base64/r/n";  //采用BASE64编码

    send (m_sock,tmp,tmp.GetLength(),0);

    tmp = "Content-Disposition: attachment; filename=";

    tmp+=pbuf;

    tmp+="/n/n";

    send (m_sock,tmp,tmp.GetLength(),0);

    HANDLE hFile, hMapping;

    if ((hFile = CreateFile(m_FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)

    {

        AfxMessageBox("could not open file");

        return ;

    } //打开文件.

    if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))

    {

        AfxMessageBox("mapping failed");

        CloseHandle(hFile);

        return ;

    } 

    if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))

    {

        AfxMessageBox("view failed");

        CloseHandle(hMapping);

        CloseHandle(hFile);

        return ;

    }  //把文件映射到内存。

    DWORD cb=GetFileSize(hFile,NULL); //取得文件大小

    char *t=(char*)malloc((cb/3)*4+4); //分配BASE64编码内存

    memset(t,0,(cb/3)*4+4);

    CBase64Encode((char*)basepointer,t,cb); //编码

    send (m_sock,(char*)t,(cb/3)*4+4,0);    //把编码后的文件发送出去

    tmp = "/n/n/n--qwertyuiop--/n/n";      

    send (m_sock,tmp,tmp.GetLength(),0);  

    UnmapViewOfFile(basepointer);

    CloseHandle(hMapping);

    CloseHandle(hFile);

    tmp = "/n/r/n./r/n";   //正文传输结束

    send (m_sock,tmp,tmp.GetLength(),0);

    recv (m_sock,buf,256,0);

    send (m_sock,"quit/n",5,0);

    AfxMessageBox("邮件发送完成");

    closesocket(m_sock);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值