正如标题所说,我想找到罗斯林的所有字符串,并能够操纵它们。我已经创建了一个程序,可以获取所有类和本地声明,但我希望有一些方法来提取字符串。
在一个最佳的世界中,我希望能够获得以下字符串的键值对,并避免使用int i = 0;
和var i2 = 0;
。
var test = "test";
string test1 = "testing";
String test2 = "testing 2";
我目前拥有的:
{
class Program
{
static void Main(string[] args)
{
var workspace = MSBuildWorkspace.Create();
SyntaxTree tree = CSharpSyntaxTree.ParseText(
@"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
var test = ""test"";
string test1 = ""testing"";
String test2 = ""testing 2"";
int i = 0;
var i2 = 0;
}
}
}");
var root = (CompilationUnitSyntax)tree.GetRoot();
var classVisitor = new ClassVirtualizationVisitor();
classVisitor.Visit(root);
var classes = classVisitor.Classes;
var localDeclaration = new LocalDeclarationVirtualizationVisitor();
localDeclaration.Visit(root);
var localDeclarations = localDeclaration.LocalDeclarations;
}
}
class LocalDeclarationVirtualizationVisitor : CSharpSyntaxRewriter
{
public LocalDeclarationVirtualizationVisitor()
{
LocalDeclarations = new List<LocalDeclarationStatementSyntax>();
}
public List<LocalDeclarationStatementSyntax> LocalDeclarations { get; set; }
public override SyntaxNode VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
{
node = (LocalDeclarationStatementSyntax)base.VisitLocalDeclarationStatement(node);
LocalDeclarations.Add(node);
return node;
}
}
class ClassVirtualizationVisitor : CSharpSyntaxRewriter
{
public ClassVirtualizationVisitor()
{
Classes = new List<ClassDeclarationSyntax>();
}
public List<ClassDeclarationSyntax> Classes { get; set; }
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
Classes.Add(node); // save your visited classes
return node;
}
}
}
示例程序:
using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
var test = "test";
string test1 = "testing";
String test2 = "testing 2";
int i = 0;
var i2 = 0;
}
}
}
使用来自Strings v2.53
的SysInternals
我在.exe
下面得到以下字符串,我想从Roslyn得到同样的结果。
https://docs.microsoft.com/sv-se/sysinternals/downloads/strings
!This program cannot be run in DOS mode.
.text
`.rsrc
@.reloc
BSJB
v4.0.30319
#Strings
#US
#GUID
#Blob
T.#]
<Module>
mscorlib
HelloWorld
DebuggableAttribute
TargetFrameworkAttribute
CompilationRelaxationsAttribute
RuntimeCompatibilityAttribute
ObfuscationConsoleApp.exe
System.Runtime.Versioning
Program
System
Main
ObfuscationConsoleApp
.ctor
System.Diagnostics
System.Runtime.CompilerServices
DebuggingModes
args
Object
test
testing
testing 2
z\V
WrapNonExceptionThrows
.NETFramework,Version=v4.6.1
FrameworkDisplayName
.NET Framework 4.6.1
RSDS
g1M
|EF\R}
C:\Users\Oscar\source\repos\ObfuscationConsoleApp\ObfuscationConsoleApp\obj\Debug\ObfuscationConsoleApp.pdb
_CorExeMain
mscoree.dll
VS_VERSION_INFO
VarFileInfo
Translation
StringFileInfo
000004b0
FileDescription
FileVersion
0.0.0.0
InternalName
ObfuscationConsoleApp.exe
LegalCopyright
OriginalFilename
ObfuscationConsoleApp.exe
ProductVersion
0.0.0.0
Assembly Version
0.0.0.0
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
非常感谢@MarcGravell和http://roslynquoter.azurewebsites.net/的服务(请务必选中“保留冗余API调用”复选框)或https://github.com/KirillOsenkov/RoslynQuoter。
打印字符串键值对的最终代码:
var localDeclaration = new LocalDeclarationVirtualizationVisitor();
localDeclaration.Visit(root);
var localDeclarations = localDeclaration.LocalDeclarations;
foreach (var localDeclarationStatementSyntax in localDeclarations)
{
foreach (VariableDeclaratorSyntax variable in localDeclarationStatementSyntax.Declaration.Variables)
{
var stringKind = variable.Initializer.Value.Kind();
if (stringKind == SyntaxKind.StringLiteralExpression)
{
Console.WriteLine($"Key: {variable.Identifier.Value} Value:{variable.Initializer.Value}");
}
}
}