닷넷 opcode 실행 예제.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Permissions;
using System.Text;
using Systehttp://m.Threading.Tasks;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
namespace dnLib
{
internal class Program
{
public static void test()
{
var sb = new StringBuilder();
sb.AppendLine("test1");
sb.AppendLine("test2");
sb.AppendLine("test3");
if (sb.ToString().Length > 10)
{
sb.AppendLine("10>");
}
var sbResult = sb.ToString();
Console.WriteLine(sbResult);
var strMsg = string.Empty;
strMsg = " TEST MSG";
strMsg += " MSG3";
strMsg += " MSG4";
Console.WriteLine(strMsg);
strMsg = " NO TEST MSG";
strMsg += " MSG2";
strMsg += " MSG3";
Console.WriteLine(strMsg);
}
static void Main(string[] args)
{
string path = @"dnlib - 복사본.exe"; // 분석할 DLL 또는 EXE
var module = ModuleDefMD.Load(path);
foreach (TypeDef type in module.Types)
{
foreach (MethodDef method in type.Methods)
{
if (!method.HasBody) continue;
Console.WriteLine(">> Method: " + method.FullName);
Simulate(method);
}
}
}
public static void Simulate(MethodDef method)
{
Stack<object> stack = new Stack<object>();
Dictionary<string, object> locals = new Dictionary<string, object>();
IList<Instruction> instructions = method.Body.Instructions;
for (int i = 0; i < instructions.Count; i++)
{
Instruction instr = instructions[i];
OpCode opcode = instr.OpCode;
object operand = instr.Operand;
// --- PUSH (ldstr)
if (opcode == OpCodes.Ldstr)
{
string str = operand as string;
stack.Push(str);
Console.WriteLine("[PUSH] \"" + str + "\"");
}
else if (opcode == OpCodes.Newobj && operand is IMethod ctor)
{
string fullTypeName = ctor.DeclaringType.FullName.Replace("/", "+");
Type type = Type.GetType(fullTypeName);
if (type != null)
{
try
{
object instance = Activator.CreateInstance(type);
stack.Push(instance);
Console.WriteLine("[NEWOBJ] 생성자 호출 → 인스턴스 push: " + fullTypeName);
}
catch (Exception ex)
{
Console.WriteLine("[!] 생성자 실행 실패: " + ex.Message);
}
}
else
{
Console.WriteLine("[!] newobj: 타입 못 찾음 → " + fullTypeName);
}
}
else if (opcode == OpCodes.Ldsfld)
{
if (operand is IField field)
{
string fullFieldName = field.FullName;
// 특수 처리: System.String::Empty
if (fullFieldName == "System.String System.String::Empty")
{
stack.Push(string.Empty);
Console.WriteLine("[LDSFLD] System.String::Empty → \"\"");
}
else
{
Console.WriteLine("[LDSFLD] 지원되지 않는 정적 필드: " + fullFieldName);
stack.Push(null); // 기본 처리
}
}
}
// --- PUSH (ldloc)
else if (opcode.Code.ToString().StartsWith("Ldloc"))
{
int index = GetLocalIndex(opcode.Code, operand, method);
string varName = "V_" + index;
object value = locals.ContainsKey(varName) ? locals[varName] : null;
stack.Push(value);
Console.WriteLine("[PUSH] " + varName + " → \"" + value + "\"");
}
// --- POP + STLOC
else if (opcode.Code.ToString().StartsWith("Stloc"))
{
int index = GetLocalIndex(opcode.Code, operand, method);
string varName = "V_" + index;
object value = stack.Pop();
locals[varName] = value;
//stack.Push(value); // 선택적
Console.WriteLine("[STLOC] " + varName + " = \"" + value + "\"");
}
else if (opcode == OpCodes.Ldc_I4_S || opcode == OpCodes.Ldc_I4)
{
int intValue = Convert.ToInt32(operand);
stack.Push(intValue);
Console.WriteLine("[PUSH] int32 " + intValue);
}
else if (opcode == OpCodes.Cgt)
{
object right = stack.Pop(); // value2
object left = stack.Pop(); // value1
int a = Convert.ToInt32(left);
int b = Convert.ToInt32(right);
int result = (a > b) ? 1 : 0;
stack.Push(result);
Console.WriteLine("[CGT] " + a + " > " + b + " → " + result);
}
else if (opcode == OpCodes.Brfalse_S || opcode == OpCodes.Brfalse)
{
if (stack.Count > 0)
{
object val = stack.Pop();
bool condition = Convert.ToInt32(val) == 0;
Instruction target = operand as Instruction;
int targetIndex = instructions.IndexOf(target);
Console.WriteLine("[BRFALSE] 조건값: " + val + " → " + (condition ? "분기함" : "계속 진행"));
if (condition)
{
i = targetIndex - 1; // for 루프 내에서 자동 증가되므로 -1
}
}
else
{
Console.WriteLine("[!] BRFALSE 조건 스택에 값 없음");
}
}
// --- POP
else if (opcode == OpCodes.Pop)
{
if (stack.Count > 0)
{
object discarded = stack.Pop();
Console.WriteLine("[POP] Discarded \"" + discarded + "\"");
}
}
// --- CALL (e.g., String.Concat)
else if (opcode == OpCodes.Call && operand is IMethod methodRefCall)
{
InvokeCallvirtWithStack(methodRefCall, stack);
}
// --- CALLVIRT (인스턴스 메서드 호출)
else if (opcode == OpCodes.Callvirt && operand is IMethod methodRefVirt)
{
InvokeCallvirtWithStack(methodRefVirt, stack);
}
}
foreach (var item in method.Body.Variables)
{
Console.WriteLine(item);
}
Console.WriteLine( );
}
// 도우미: 로컬 변수 인덱스 계산
private static int GetLocalIndex(Code code, object operand, MethodDef method)
{
if (code == Code.Stloc_0 || code == Code.Ldloc_0) return 0;
if (code == Code.Stloc_1 || code == Code.Ldloc_1) return 1;
if (code == Code.Stloc_2 || code == Code.Ldloc_2) return 2;
if (code == Code.Stloc_3 || code == Code.Ldloc_3) return 3;
Local local = operand as Local;
if (local != null)
return method.Body.Variables.IndexOf(local);
return -1;
}
// 핵심: callvirt 명령 실행
public static void InvokeCallvirtWithStack(IMethod methodRef, Stack<object> ilStack)
{
string fullTypeName = methodRef.DeclaringType.FullName.Replace("/", "+");
string methodName = methodRef.Name;
Type type = Type.GetType(fullTypeName);
if (type == null)
{
Console.WriteLine("[!] 타입을 찾을 수 없습니다: " + fullTypeName);
return;
}
int paramCount = methodRef.MethodSig.Params.Count;
List<object> argsList = new List<object>();
for (int i = 0; i < paramCount; i++)
{
if (ilStack.Count > 0)
{
object arg = ilStack.Pop();
argsList.Add(arg);
Console.WriteLine("[STACK POP] arg[" + i + "] = \"" + arg + "\"");
}
else
{
argsList.Add(null);
Console.WriteLine("[STACK MISS] arg[" + i + "] = null");
}
}
argsList.Reverse();
object[] paramValues = argsList.ToArray();
Type[] paramTypes = new Type[paramCount];
for (int i = 0; i < paramCount; i++)
{
paramTypes[i] = typeof(string); // 간단화: 모두 string 처리
}
MethodInfo methodInfo = type.GetMethod(methodName, paramTypes);
if (methodInfo == null)
{
Console.WriteLine("[!] 메서드 못 찾음: " + methodName);
return;
}
object instance;
if (ilStack.Count > 0) instance = ilStack.Pop();
else
{
try
{
instance = methodInfo.IsStatic ? null : Activator.CreateInstance(type);
//instance = Activator.CreateInstance(type);
Console.WriteLine("[✓] 인스턴스 생성: " + fullTypeName);
}
catch (Exception ex)
{
Console.WriteLine("[!] 인스턴스 생성 실패: " + ex.Message);
return;
}
}
try
{
object result = methodInfo.Invoke(instance, paramValues);
Console.WriteLine("[✓] callvirt 실행 완료 → 반환값: " + (result ?? "(void)"));
if (result != null)
{
ilStack.Push(result);
Console.WriteLine("[PUSH] 반환값 \"" + result + "\"");
}
}
catch (Exception ex)
{
Console.WriteLine("[!] 호출 오류: " + ex.Message);
}
}
}
}