タイトルにはC#、DLLと書きましたが.NetやMonoで作成されたものなら大抵大丈夫です。
今回はMono.Cecil
を利用してDLLから文字列を抽出しました。
Mono.Cecil
を使用すると簡単にDLLやEXEの中身を確認したり変更したりすることができて便利です。
Mono.Cecil
はNuGetからインストールできるので簡単に使用することができます。
showString.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 1)
{
var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(args[0]);
assembly.Modules
.SelectMany(x => x.Types)
.ToList()
.ForEach((type) =>
{
showString(type, assembly);
});
}
else
{
Console.WriteLine("引き数にdllかexeを指定してください。");
}
}
static private void showString(Mono.Cecil.TypeDefinition type, Mono.Cecil.AssemblyDefinition assembly, string prefix = "")
{
if (prefix != "")
{
prefix += ".";
}
if (type.Namespace != "")
{
prefix += type.Namespace + ".";
}
prefix += type.Name;
type.NestedTypes.ToList().ForEach(x => {
showString(x, assembly, prefix);
});
type.Methods.ToList().ForEach((method) =>
{
var lineCount = 0;
if (method.HasBody)
{
method.Body.Instructions.ToList().ForEach(inst =>
{
if (inst.OpCode == Mono.Cecil.Cil.OpCodes.Ldstr)
{
if (lineCount == 0)
{
Console.WriteLine(string.Format("{0}.{1}:", prefix, method.Name));
}
Console.WriteLine(string.Format("{0}:{1}", lineCount, inst.Operand.ToString()));
lineCount++;
}
});
}
if (lineCount != 0)
{
Console.WriteLine();
}
});
}
}
}
このプログラムでこのプログラムから文字列を抽出すると以下のようになります。
ConsoleApplication2.Program.<>c__DisplayClass3.<Main>b__0:
0:
ConsoleApplication2.Program.<>c__DisplayClass8.<>c__DisplayClassb.<showString>b__7:
0:{0}.{1}:
1:{0}:{1}
ConsoleApplication2.Program.Main:
0:引き数にdllかexeを指定してください。
ConsoleApplication2.Program.showString:
0:
1:.
2:
3:.
参考
How to search for a string in a compiled assembly using Reflection or Mono.Cecil?