forked from TitleOS/QuantumTunnel
-
Notifications
You must be signed in to change notification settings - Fork 1
/
QuantumTunnel.cs
149 lines (132 loc) · 5.97 KB
/
QuantumTunnel.cs
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using CommandLine;
namespace QuantumTunnel
{
internal static class Flash
{
private static readonly string RawFlashDeviceName = "\\\\.\\Xvuc\\Flash";
private static readonly string FlashDeviceName = "\\\\.\\Xvuc\\FlashFs";
/// <summary>
/// Read raw flash image.
/// </summary>
/// <param name="outputFile">Filepath to save the flashdump.</param>
/// <returns>Zero on success, Non-Zero on failure</returns>
public static int ReadFlashImage(string outputFile)
{
return ReadInternal(RawFlashDeviceName, outputFile);
}
/// <summary>
/// Read single file from flash filesystem.
/// </summary>
/// <param name="targetFile">Filename of file to read.</param>
/// <param name="outputFile">Filepath to save the file.</param>
/// <returns>Zero on success, Non-Zero on failure</returns>
public static int ReadFlashFsFile(string targetFile, string outputFile)
{
string fullpath = FlashDeviceName + "\\" + targetFile;
return ReadInternal(fullpath, outputFile);
}
/// <summary>
/// Reads from opened DeviceHandle until EOF is signalled.
/// </summary>
/// <param name="devicePath">Full device path (e.g. \\.\Xvuc\FlashFs\filename.bin)</param>
/// <param name="outputFile">Filepath to save the file.</param>
/// <returns>Zero on success, Non-Zero on failure</returns>
public static int ReadInternal(string devicePath, string outputFile)
{
IntPtr pHandle = KernelBase.CreateFile(devicePath, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite, IntPtr.Zero, System.IO.FileMode.Open, System.IO.FileAttributes.Normal, IntPtr.Zero);
if (pHandle == IntPtr.Zero)
{
Console.WriteLine("Failed to get handle to {0}", devicePath);
return -3;
}
bool success = false;
uint numBytesRead = 0;
ulong bytesReadTotal = 0;
byte[] buf = new byte[1024 * 1024]; // 1kb
using (FileStream fsOutputFile = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
{
do
{
success = KernelBase.ReadFile(pHandle, buf, (uint)buf.Length, out numBytesRead, IntPtr.Zero);
if (!success && bytesReadTotal == 0 && numBytesRead == 0)
{
Console.WriteLine("Failed to ReadFile {0}, error: 0x{1:X}", devicePath, KernelBase.GetLastError());
KernelBase.CloseHandle(pHandle);
return -4;
}
fsOutputFile.Write(buf, 0, (int)numBytesRead);
bytesReadTotal += numBytesRead;
}
while (numBytesRead > 0);
}
Console.WriteLine("Read {0} bytes", bytesReadTotal);
KernelBase.CloseHandle(pHandle);
return 0;
}
}
internal static class KernelBase
{
[DllImport("kernelbase.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPWStr)] string filename,
[MarshalAs(UnmanagedType.U4)] FileAccess access,
[MarshalAs(UnmanagedType.U4)] FileShare share,
IntPtr securityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
IntPtr templateFile);
[DllImport("kernelbase.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernelbase.dll", SetLastError = true)]
public static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernelbase.dll")]
public static extern uint GetLastError();
}
class CommandLineOptions
{
[Value(index: 0, Required = false, HelpText = "File to dump from FlashFs.")]
public string TargetFile { get; set; }
[Option(shortName: 'o', longName: "output", Required = false, HelpText = "Output filepath.")]
public string OutputFile { get; set; }
[Option(shortName: 'r', longName: "rawdump", Required = false, HelpText = "Toggle raw flashimage dumping.")]
public bool DoRawdump { get; set; }
}
class QuantumTunnel
{
/// <param name="rawdump">Dump full raw flash</param>
/// <param name="filename">Filename of file to dump from FlashFs</param>
/// <param name="output">Output filepath</param>
static int Main(string[] args)
{
Console.WriteLine("QuantumTunnel - C# FlashFS Reader");
var exitCode = Parser.Default.ParseArguments<CommandLineOptions>(args)
.MapResult(
(CommandLineOptions opts) => {
if (!String.IsNullOrEmpty(opts.TargetFile))
{
return Flash.ReadFlashFsFile(opts.TargetFile, opts.OutputFile ?? opts.TargetFile);
}
else if (opts.DoRawdump)
{
return Flash.ReadFlashImage(opts.OutputFile ?? "flash.bin");
}
else
{
Console.WriteLine("Error: Neither filename or rawdump flag provided!");
return -2;
}
},
_ => {
Console.WriteLine("Error parsing arguments! Use --help!");
return -1;
});
return exitCode;
}
}
}